• 设计模式笔记 ------ 状态模式


      现在的面向对象软件开发过程中,对象便是核心。而对象在不同的情况下会表现出不同的行为,这便是状态。我们也许会用一堆 if-else 判断,或者 switch-case 状态机,但在复杂的状态情况下,状态模式应运而生。

    状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

      结构类图如下

      上图中包括:

      1、环境类(Context): 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。

      2、抽象状态类(AbstractState): 定义一个接口以封装与Context的一个特定状态相关的行为。

      3、具体状态类(ConcreteState): 每一子类实现一个与Context的一个状态相关的行为。

      

      下面看个例子:假设现在有一个开关,控制三种颜色的切换,blue,green,red,蓝色下一个绿色,绿色下一个红色,红色下一个是蓝色,也可以倒过来。

      首先是抽象状态类

    /* 
     * 抽象状态类,执行上一个下一个的操作,还可以获得当前的状态 
     * 当然在这可以既执行别的操作,比如开关拨到某个颜色的时候,颜色对应的灯亮 
     */  
      
    public interface State {  
      
        public  void last(Context c);  
      
        public  void next(Context c);  
          
        public  String getState();  
      
      
    }  
    

       其次是具体状态类

    /* 
     * 蓝色状态类,实现的接口的方法,通过状态管理器在上一个或者下一个方法中 
     * 设置改变后的状态 
     */  
    public class BlueState implements State {  
      
        public String getState() {  
            // TODO Auto-generated method stub  
            return "blue";  
        }  
      
        public void last(Context c) {  
            c.setState(new GreenState());  
      
        }  
      
        public void next(Context c) {  
            c.setState(new RedState());  
      
        }  
      
    }  
    /* 
     * 绿色状态类,实现的接口的方法,通过状态管理器在上一个或者下一个方法中 
     * 设置改变后的状态 
     */  
    public class GreenState implements State {  
      
        public String getState() {  
              
            return "green";  
        }  
      
        public void last(Context c) {  
            c.setState(new RedState());  
      
        }  
      
        public void next(Context c) {  
        c.setState(new BlueState());  
      
        }  
      
    }  
    /* 
     * 红色状态类,实现的接口的方法,通过状态管理器在上一个或者下一个方法中 
     * 设置改变后的状态 
     */  
     public class RedState implements State {  
      
    public String getState() {  
        return "red";  
    }  
      
    public void last(Context c) {  
    c.setState(new BlueState());  
      
    }  
      
    public void next(Context c) {  
        c.setState(new GreenState());  
      
    }  
    

       最后是环境类

    /* 
     * 环境类,设置初始状态,得到当前状态, 
     * 提供了两个操作,上一个的操作方法中,调用了当前状态的last方法,将状态管理器的状态更新 
     *                下一个的操作方法中,调用了当前状态的next方法,将状态管理器的状态更新 
     */  
    public class Context {  
          
        private State state = null;  
      
        public State getState() {  
            return state;  
        }  
      
        public void setState(State state) {  
            this.state = state;  
        }  
          
        public void push(){  
              
            state.last(this);  
            System.out.println(state.getState());  
        }  
          
        public void pull(){  
              
            state.next(this);  
            System.out.println(state.getState());  
        }  
          
      
    }  
    

       测试类

    /* 
     * 测试类 
     */  
    public class Client{  
      
        public static void main(String[] args) throws InterruptedException {  
            /* 
             * 创建一个状态管理器,设置初始状态为红色, 
             * 然后就可以执行状态管理器的last或者next方法 
             */  
            Context c = new Context();  
            State redsState = new RedState();         
            c.setState(redsState);  
                while (true){  
                    System.out.println("当前状态:"+c.getState().getState());  
                    System.out.print("上一个状态: ");  
                     c.push();  
                     Thread.currentThread().sleep(2000);  
                }          
        }  
          
    }  
    

     结果为

      从上面的例子可以看出一些状态模式的优缺点:

      优点:

    1、它将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
    2、它使得状态转换显式化。
    3、State对象可被共享。

      缺点:

    1、状态模式的使用必然会增加系统类和对象的个数。
    2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

      总结:状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。

  • 相关阅读:
    阿里P7架构师是如何解决跨域问题的!你有遇到吗?
    Node.js Express 框架
    用户管理 之 Linux 系统中的超级权限的控制
    [转] Exchange 2013 安装部署详解
    Clustered和Nonclustered Indexes 各自得特点和区别及长短处
    配置IIS5.5/6.0 支持 Silverlight
    redis模块使用
    redis介绍及安装
    linux上安装redis、远程配置及开机启动
    远程连接linux、配置SSHD
  • 原文地址:https://www.cnblogs.com/adamJin/p/7412089.html
Copyright © 2020-2023  润新知