设计模式-状态模式(State Pattern)

本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/

 

状态模式简介

状态模式允许一个对象在其内部状态改变的时候改变它的行为,他的内部会存着好几种状态,在当前状态发生变化是,这个对象执行和之前相同的操作也会有不同的作用效果。

 

状态模式的定义和基本结构

定义:状态模式允许一个对象在其内部状态改变的时候改变它的行为,就像变成了另一个对象一样。

 

一张来自《Head First》的结构图

Context:这个类里面包含了很多种状态类,当前状态不同时,这个类的行为会发生变化。

State:所有状态类的超类,也是Context里使用状态类的接口,里面包含了所以会引起状态变化的方法。

ConcreteState:某种状态的实现。

 

一个简单的例子(java)

假设我们有一个多功能灯,只有一个按钮,灯有如下状态:关闭、白光、暖光、舞台灯光。按下按钮,灯就在这4个状态中依次切换。我们用状态模式来模拟这个过程。我们需要一个MyLamp类,一个State超类,和四个状态类。

首先给出State超类,和4个状态类。因为我们只有一个改变状态的操作,所以只有一个方法就够了,另外状态类和MyLamp类耦合比较强,所以先写那个都无所谓(反正中途会碰到未声明的错误)。

 1 public abstract class State {
 2     private MyLamp lamp;
 3     public State(MyLamp lamp){
 4         this.lamp=lamp;
 5     }
 6     public MyLamp getLamp() {
 7         return lamp;
 8     }
 9     public abstract void pushButton();
10 }
11 
12 public class LampClose extends State {
13     public LampClose(MyLamp lamp) {
14         super(lamp);
15     }
16     @Override
17     public void pushButton() {
18         getLamp().setCurrentState(getLamp().getLw());
19         System.out.println("当前状态:"+getLamp().getCurrentState().getClass().getName());
20     }
21 }
22 
23 public class LampWhite extends State {
24     public LampWhite(MyLamp lamp) {
25         super(lamp);
26     }
27     @Override
28     public void pushButton() {
29         getLamp().setCurrentState(getLamp().getLf());
30         System.out.println("当前状态:"+getLamp().getCurrentState().getClass().getName());
31     }
32 }
33 
34 public class LampFluorescent extends State {
35     public LampFluorescent(MyLamp lamp) {
36         super(lamp);
37     }
38     @Override
39     public void pushButton() {
40         getLamp().setCurrentState(getLamp().getLcf());
41         System.out.println("当前状态:"+getLamp().getCurrentState().getClass().getName());
42     }
43 }
44 
45 public class LampColourful extends State {
46     public LampColourful(MyLamp lamp) {
47         super(lamp);
48     }
49     @Override
50     public void pushButton() {
51         getLamp().setCurrentState(getLamp().getLc());
52         System.out.println("当前状态:"+getLamp().getCurrentState().getClass().getName());
53     }
54 }

 

 

然后给出MyLamp类的实现。

 1 public class MyLamp {
 2     private LampClose lc;
 3     private LampWhite lw;
 4     private LampFluorescent lf;
 5     private LampColourful lcf;
 6     private State currentState;
 7     public MyLamp(){
 8         lc=new LampClose(this);
 9         lw=new LampWhite(this);
10         lf=new LampFluorescent(this);
11         lcf=new LampColourful(this);
12         currentState=lc;
13         System.out.println("当前状态:"+getCurrentState().getClass().getName());
14     }
15     public void push(){
16         currentState.pushButton();
17     }
18     public State getCurrentState() {
19         return currentState;
20     }
21     public void setCurrentState(State currentState) {
22         this.currentState = currentState;
23     }
24     public LampClose getLc() {
25         return lc;
26     }
27     public LampWhite getLw() {
28         return lw;
29     }
30     public LampFluorescent getLf() {
31         return lf;
32     }
33     public LampColourful getLcf() {
34         return lcf;
35     }
36 }

 

 

最后给出测试类。

 1 public class Test {
 2     public static void main(String[] args) {
 3         MyLamp ml=new MyLamp();
 4         ml.push();
 5         ml.push();
 6         ml.push();
 7         ml.push();
 8         ml.push();
 9         ml.push();
10         ml.push();
11         ml.push();
12         ml.push();
13         ml.push();
14         ml.push();
15     }
16 }

 

 

测试中,我们不停的调用push()方法,我们会发现输出是不一样的,因为MyLamp的状态一直在不停转换。

输出如下:

 

 

状态模式和策略模式

敏感的朋友可能发现状态模式和策略模式的类图看起来一模一样,确实,他们有着相似的地方,但是他们的内涵差距还是挺大的,策略模式中,策略的决定权在用户手中,用户决定给类set哪一个需要的策略类,而状态模式中,context类里面已经包含了所有的状态类,转换规则也已经内化到了代码中,用户只需要执行操作,状态的转换对应用户来说是透明的,他们能感觉到的只有类的行为的变化而已。

 

状态模式到此结束,♪(^∇^*)

 

参考资料:《Head First 设计模式》

posted @ 2016-07-23 22:20  呆代待殆  阅读(286)  评论(0编辑  收藏  举报