1

我有一个简单的状态机,现在受到许多特殊情况的干扰。

最初:

void state(SomeObject o) {
   doStep1();
   doStep2();
   doStep3();
}

现在,someobject 有一个名为 type 的字段——比如 typeA、typeB、typeC。typeC 需要一些特殊处理。

   void state(SomeObject o) {
       doStep1();  
       doStep2();
       if (o.type == typeC) { o.doFoo(); } 
       doStep3();
       if (o.type == typeC) { o.doFoo(); } 
    }

显然,这段代码不可扩展且脆弱。我有第 4 种类型,称为 typeD,它只会增加更多的 if-else。在这种情况下使用哪种模式?如果我确实使用多态性,假设一个接口 SomeObject,它有 4 个 ABC 和 D 类型的实现,我担心 A 和 B 会有 doFoo() 的空实现,这是不好的。有什么好的设计模式吗?

4

1 回答 1

6

state正如您已经指出的那样,逻辑是不灵活的。例如,如果对于某些对象,我们需要以不同的顺序(3->1->2)执行操作,则问题可能会变得更加复杂。

由于行为主要取决于SomeObject类型,我相信一种“干净”的方法是将每个对象转换为一组可组合的命令(命令模式+复合/装饰器)。

/* Declare an interface for executing an operation */
public interface Command
{
    public void execute();
    public Command setNext();
    public Boolean hasNext();
}
/* Abstract class providing compose-ability and chaining behavior for its children.
*/
public abstract class BaseCommand implements Command
{
    private Command next;

    public Boolean hasNext()
    {
        return next != null;
    }
    public Command setNext(Command nextC)
    {
        next = nextC;
        return nextC;
    }
    public void execute(){
        executeImpl();
        if(hasNext()) next.execute();
    }

    public abstract void executeImpl();
}

现在,您可以定义一组与特定处理相对应的命令(每个命令都将直接映射到您的状态方法的特定“行”/步骤)。

public class Step1Command extends BaseCommand
{
    // If we need access to the SomeObject instance we can define a dependecy on it
    // ex. through a constructor

    //The necessary processing goes here
    public void executeImpl(){
         doStep1();
    }
}

最后,您需要将您的对象转换为一组命令,这可以通过工厂类来实现:

public class CommandFactory
{

    //The necessary processing goes here
    public Command create(SomeObjectA typeA){
         Command firstCommand = new Step1Command(typeA);
         Command secondCommand = new Step2Command(typeA);
         //....
         Command lastCommand = new StepXCommand(typeA);
         //We can easily switch the order of processing for a particular object
         fistCommand.setNext(secondCommand)
                    //...
                    .setNext(lastCommand);

         return firstCommand;
    }
}

你的代码现在看起来如何?

CommandFactory cFactory = new CommandFactory();
void state(SomeObject o) {
   Command command = cFactory.create(o);
   command.execute();
}

那么,有什么附加价值(因为这可能看起来有点矫枉过正)?

  1. state取决于对象类型的处理从方法中移开。方法重载 + 继承应该允许您绕过 if/else。

  2. 您可以轻松切换必要处理的顺序(),这使得逻辑更加灵活。

  3. 添加新的 SomeObject 实现处理不会改变您现有的代码(可维护性+可扩展性)

于 2013-11-12T10:12:35.000 回答