状态模式——HeadFirst设计模式学习笔记

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类

——将状态封装成独立的类,将动作委托给当前状态对象,所以行为会随着内部状态的变化而变化

 

状态转换图:为每一个状态创建一个实现一组相同操作接口的对象,实体对象包含所有状态并有一个当前状态接口的引用

特点:

  • 允许一个对象基于不用的状态有不同的行为
  • 把变化的东西取出来,局部化每个状态的行为,每个状态的行为局部化到自己的类中,遵守“封装变化”原则,减少了繁琐的if语句,满足“对修改关闭,对扩展开放”原则,便于阅读与理解
  • 所有的状态实现共同的state接口,state接口可以作为抽象类,减少代码冗余,默认实现可以作为不支持操作
  • 实体对象包含它的每一个状态,当前状态总是这些状态之一,当动作被调用时,它会把动作委派给当前的状态完成

注意:

  • 状态的转换可以在Context中实现(状态转换是固定的),亦可在具体的状态类中实现(状态转化是动态的,状态类之间产生了依赖)
  • 客户不可以直接改变Context中的状态
  • 状态可以被共享
  • 明确主机的行为与主机的状态的之间的关系,主机的某种状态的操作可以操作主机的行为。例: 

状态模式vs策略模式: 

  • 均允许对象通过组合和委托拥有不同的行为或算法
  • 状态模式的的当前状态游走于对象的状态集合之间,状态的改变是有方案的,客户不了解状态变化的方式;策略模式客户主动指定状态中的哪一个

举例:

实现糖果自动贩卖机过程,状态转换图如上 

状态接口及SoldState实现:

 1 public interface State {  
 2    public void insertQuarter();   // 投入25分钱  
 3    public void ejectQuarter();    // 拒绝25分钱  
 4    public void turnCrank();       // 转动曲柄  
 5    public void dispense();        // 发放糖果  
 6 } 
 7 
 8 
 9 public class SoldState implements State{  
10       
11     GumballMachine gumballMachine;  
12     public SoldState(GumballMachine gumballMachine) {  
13         this.gumballMachine = gumballMachine;  
14     }  
15     // 投入25分钱  
16     public void insertQuarter() {  
17         System.out.println("Please wait, we're already giving you a gumball");  
18     }  
19     // 拒绝25分钱  
20     public void ejectQuarter() {  
21         System.out.println("Sorry,you have already turn crank");  
22     }  
23     // 转动曲柄  
24     public void turnCrank() {  
25         System.out.println("trun twice ,doesn't give you anthor gamball!");  
26     }  
27     // 发放糖果  
28     public void dispense() {  
29         gumballMachine.releaseBall();  
30         if(gumballMachine.getCount()>0){  
31             gumballMachine.setState(gumballMachine.getNoQuarterState());  
32         } else {  
33             System.out.println("Opps,out of gamball!");   
34             gumballMachine.setState(gumballMachine.getSoldOutState());  
35         }  
36     }  
37 } 

自动贩卖机实现:

 1 public class GumballMachine {  
 2     //状态实例  
 3     State soldOutState;  
 4     State noQuarterState;  
 5     State hasQuarterState;  
 6     State soldState;  
 7     State winnerState;  
 8       
 9     // 实例变量state,初始化为糖果售罄状态  
10     State state = soldOutState;   
11     // 记录机器内装有糖果的数目,开始机器是没有装糖果的  
12     int count=0;  
13     // 构造器取得糖果的初始数目并把它放在一个实例变量count中  
14     public GumballMachine(int numberGumballs) {  
15         // 每种状态都创建一个状态实例  
16         soldOutState=new SoldOutState(this);  
17         noQuarterState=new NoQuarterState(this);  
18         hasQuarterState=new HasQuarterState(this);  
19         soldState=new SoldState(this);  
20         winnerState = new WinnerState(this);  
21           
22         this.count = numberGumballs;  
23         // 若超过0颗糖果,就将状态设置为NoQuarterState  
24         if(numberGumballs > 0) {  
25             state = noQuarterState;  
26         }  
27     }  
28     // 取得机器内的糖果数目  
29     public int getCount() {  
30         return count;  
31     }  
32     // 取得糖果售罄状态  
33    // ……
34 
35     // 投入25分钱  
36     public void insertQuarter(){  
37         state.insertQuarter();  
38     }  
39     // 拒绝25分钱  
40     public void ejectQuarter(){  
41         state.ejectQuarter();  
42     }  
43     // 转动曲柄  
44     public void turnCrank(){  
45         state.turnCrank();  
46         state.dispense();  
47     }  
48     // 设置状态  
49     public void setState(State state){  
50         this.state=state;  
51     }  
52     // 糖果滚出来一个  
53     public void releaseBall(){  
54         System.out.println("A gumball comes rolling out of the solt...");  
55         if(count!=0){  
56             count--;  
57         }  
58     }  
59 }  
原文地址:https://www.cnblogs.com/HectorHou/p/6012179.html