有没有设计模式/方法/方式可以消除嵌套的if-then-else条件/switch语句?
我记得在Google的一篇博客文章中看到过一些方法,但现在好像找不到了。
有没有设计模式/方法/方式可以消除嵌套的if-then-else条件/switch语句?
我记得在Google的一篇博客文章中看到过一些方法,但现在好像找不到了。
你读过Coding Horror上关于简化箭头代码的this吗?
如果你使用一种没有异常处理机制的编程语言,可以将throw替换为return或goto。
您希望使用重构来替换使用多态类的条件语句,例如example。
或者这里有另一个example
基本上,理想情况下非常简单,您创建一个对象层次结构,并将各种行为移动到重写方法中。您仍需要一个方法来创建正确的类,但可以使用工厂模式来完成此操作。
让我补充一下,这并不是每种情况下都是完美的解决方案。正如(抱歉,我忘记您的名字了)在我的评论中指出的那样,有时这可能很麻烦,特别是如果您必须创建一个对象模型才能做到这一点。如果您拥有以下内容,则此重构将非常出色:
function doWork(object x)
{
if (x is a type of Apple)
{
x.Eat();
} else if (x is a type of Orange)
{
x.Peel();
x.Eat();
}
}
在这里,您可以将开关重构为每种水果都会处理的新方法。
正如有人指出如何创建正确的类型以进入doWork,有更多解决此问题的方法,我可能无法列出一些基本方法。第一个和最直接的(是的,违反了这个问题的规则)是一个开关:
class FruitFactory
{
Fruit GetMeMoreFruit(typeOfFruit)
{
switch (typeOfFruit)
...
...
}
}
使用多态性来获得所需的正确运行时行为,而无需条件语句。
将所有条件语句移到某种“工厂”中,在运行时将适当的类型交给您。
完成了。是不是很容易?:)
你可能想要看一下策略模式,它可以避免使用长串的if语句和链接条件。相反,你可以将每个条件抽象成一个不同的对象,每个对象定义其特定的行为。
定义这些对象的类将实现一个接口,该接口将由父对象调用。
您没有说明使用的是哪种编程语言,但如果您正在使用诸如C++、C#或Java之类的面向对象编程语言,通常可以使用虚函数来解决与switch
语句相同的问题,并且以更具扩展性的方式实现。以C++为例:
class X {
public:
int get_type(); /* Or an enum return type or similar */
...
};
void eat(X& x) {
switch (x.get_type()) {
TYPE_A: eat_A(x); break;
TYPE_B: eat_B(x); break;
TYPE_C: eat_C(x); break;
}
}
void drink(X& x) {
switch (x.get_type()) {
TYPE_A: drink_A(x); break;
TYPE_B: drink_B(x); break;
TYPE_C: drink_C(x); break;
}
}
void be_merry(X& x) {
switch (x.get_type()) {
TYPE_A: be_merry_A(x); break;
TYPE_B: be_merry_B(x); break;
TYPE_C: be_merry_C(x); break;
}
}
使用
class Base {
virtual void eat() = 0;
virtual void drink() = 0;
virtual void be_merry() = 0;
...
};
class A : public Base {
public:
virtual void eat() { /* Eat A-specific stuff */ }
virtual void drink() { /* Drink A-specific stuff */ }
virtual void be_merry() { /* Be merry in an A-specific way */ }
};
class B : public Base {
public:
virtual void eat() { /* Eat B-specific stuff */ }
virtual void drink() { /* Drink B-specific stuff */ }
virtual void be_merry() { /* Be merry in an B-specific way */ }
};
class C : public Base {
public:
virtual void eat() { /* Eat C-specific stuff */ }
virtual void drink() { /* Drink C-specific stuff */ }
virtual void be_merry() { /* Be merry in a C-specific way */ }
};
优点是您可以添加新的Base
派生类D
、E
、F
等,而无需触及任何仅涉及指向或引用Base
的代码,因此没有任何东西会过时,就像在原始解决方案中switch
语句一样。 (在Java中,转换看起来非常相似,其中方法默认为虚拟方法,我确信在C#中也是如此。)在大型项目中,这是一个巨大的可维护性优势。
/* Code Block 1... */
if(/* result of some condition or function call */)
{
/* Code Block 2... */
if(/* result of some condition or function call */)
{
/* Code Block 3... */
if(/* result of some condition or function call */)
{
/* Code Block 4... */
}
}
}
变成这样:
/* Code Block 1... */
IsOk = /* result of some condition or function call */
if(IsOK)
{
/* Code Block 2... */
IsOk = /* result of some condition or function call */
}
if(IsOK)
{
/* Code Block 3...*/
IsOk = /* result of some condition or function call */
}
if(IsOK)
{
/* Code Block 4...*/
IsOk = /* result of some condition or function call */
}
/* And so on... */
如果合适的话,当IsOk变为false时,您当然可以返回。