具有特定行为的状态机的良好设计模式

时间:2013-11-12 02:37:21

标签: java design-patterns

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

最初:

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(); } 
    }

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

1 个答案:

答案 0 :(得分:4)

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 / elses。

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

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