美文网首页设计模式笔记
设计模式笔记(十二): 状态模式

设计模式笔记(十二): 状态模式

作者: yeonon | 来源:发表于2018-07-31 13:28 被阅读13次

    我们写代码的时候,经常会用到逻辑判断if-else结构,特别是写业务代码的时候。之所以要用if-else结构是因为有某状态需要处理或者状态转移。例如Java的Thread类里定义了一个State枚举类,里面定义了线程的6个状态。这6个状态的变更并不是顺序变更的,其状态转移有时候是不确定的,所以如果不做特殊处理,仅仅使用If-lese来判断状态后做相应的处理,可能需要类似下面这样的代码:

    //下面都是伪代码
    
    if (state == NEW)
      handlerNEW()
    else if (state == RUNNABLE)
      handlerRun()
    ......
    

    例如如果状态是RUNNABLE,在处理状态的该状态的方法里,又需要若干个if-else来决定应该转移到哪个状态。即使程序员的逻辑非常严密,完整的处理了所有可能的状态。这样的写法也显得非常糟乱,而且如果现在加入一个新的状态,是不是又得费劲去处理这个新的状态。在阿里巴巴Java开发手册里有类似这样的一条建议:尽量少用if-else结构,如果非用使用,也不要超过三层。超过的话,应考虑使用状态设计模式。

    状态模式

    状态模式的类图大概是这样的:


    状态模式类图(摘自书上)

    State是接口,ConcreteStateA和ConcreteStateB是其实现类,Context可以看做是管理状态的类,里面包含了state的引用,可以通过改变这个引用的指向进行状态的转移。

    下面是简单的代码实现:

    
    //状态的抽象接口(可以有多个方法,看具体需求)
    public interface State {
    
        void handle();
    }
    
    //状态的实现类
    public class AState implements State {
    
    
        @Override
        public void handle() {
            System.out.println("handle A state");
        }
    }
    
    //状态的实现类
    public class BState implements State {
        @Override
        public void handle() {
            System.out.println("handle B state");
        }
    }
    
    //状态的上下文,即管理状态的类
    public class Context {
    
        private State state;
    
        public void request() {
            state.handle();
        }
    
        public void setState(State state) {
            this.state = state;
        }
    }
    
    //测试类
    public class Main {
    
        public static void main(String[] args) {
            Context context = new Context();
            //设置初始状态
            context.setState(new AState());
            context.request();
            //假设发生了某一事件导致了状态的切换(由A状态切换到B状态)
            context.setState(new BState());
            context.request();
        }
    }
    
    

    上面的类图和代码实现都比较简单,关键就是将每一个具体的状态作为一个单独的类来处理,然后由一个管理状态的类来管理这些状态,例如状态的改变。

    状态模式的特点

    1. 封装性较好。将对象的行为封装到单独的一个类中,隐藏类具体的实现逻辑,这样可以对状态做一个集中的管理(Context类),使得状态转移的逻辑较为清晰。
    2. 扩展性并不是很好,但是也有一定的扩展性。如果新增一个状态,可以直接实现State接口,实现相关逻辑即可。但是如果该状态和其他状态的联系较为紧密,那么可能会导致需要到原来的状态里去修改源码,有点不遵循“开闭原则”。

    小结

    现在可以给出状态模式的定义了:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

    本系列文章参考书籍是《Head First 设计模式》,文中代码示例出自书中。

    相关文章

      网友评论

        本文标题:设计模式笔记(十二): 状态模式

        本文链接:https://www.haomeiwen.com/subject/ctacvftx.html