码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式之禅之设计模式-状态模式

时间:2016-01-28 10:46:28      阅读:274      评论:0      收藏:0      [点我收藏+]

标签:

一:状态模式定义
        --->当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类
        --->状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样
        --->状态模式相对来说比较复杂,它提供了一种对物质运动的另一个观察视角,通过状态变更促使行为的变化,就类似水的状态变更一样,一碗水的初始状态是液态,通过加热转变为气态,状态的改变同时也引起体积的扩大,然后就产生了一个新的行为:鸣笛或顶起壶盖,瓦特就是这么发明蒸汽机的
        
二:状态模式角色
技术分享
        ● State——抽象状态角色接口或抽象类
                负责对象状态定义,并且封装环境角色以实现状态切换。
        ● ConcreteState——具体状态角色
                每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。
        ● Context——环境角色
                定义客户端需要的接口,并且负责具体状态的切换。


【*****】环境角色不成文的约束
        ● 把状态对象声明为静态常量,有几个状态对象就声明几个静态常量。
        ● 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。
三:状态模式的应用
【1】状态模式的优点
● 结构清晰
        避免了过多的switch...case或者if...else语句的使用,避免了程序的复杂性,提高系统的可维护性。
● 遵循设计原则
        很好地体现了开闭原则和单一职责原则,每个状态都是一个子类,你要增加状态就要增加子类,你要修改状态,你只修改一个子类就可以了。
● 封装性非常好
        这也是状态模式的基本要求,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。

【2】状态模式的缺点
        状态模式既然有优点,那当然有缺点了。但只有一个缺点,子类会太多,也就是类膨胀。如果一个事物有很多个状态也不稀奇,如果完全使用状态模式就会有太多的子类,不好管理,这个需要大家在项目中自己衡量。其实有很多方式可以解决这个状态问题,如在数据库中建立一个状态表,然后根据状态执行相应的操作,这个也不复杂,看大家的习惯和嗜好了。

【3】状态模式的使用场景
● 行为随状态改变而改变的场景
          这也是状态模式的根本出发点,例如权限设计,人员的状态不同即使执行相同的行为结果也会不同,在这种情况下需要考虑使用状态模式。
● 条件、分支判断语句的替代者
        在程序中大量使用switch语句或者if判断语句会导致程序结构不清晰,逻辑混乱,使用状态模式可以很好地避免这一问题,它通过扩展子类实现了条件的判断处理。


【4】状态模式的注意事项
        状态模式适用于当某个对象在它的状态发生改变时,它的行为也随着发生比较大的变化,也就是说在行为受状态约束的情况下可以使用状态模式,而且使用时对象的状态最好不要超过5个


四:状态模式的案例

【1】电梯四个状态所作的固定的反应

技术分享

【1】电梯的状态抽象

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 抽象电梯状态
 4  * 
 5  * (1)依赖:环境角色
 6  * (2)不同状态下的行为
 7  * @author sxf
 8  *
 9  */
10 public  abstract class LiftState {
11 
12     //定义一个环境角色,也就是封装状态的变化引起功能的变化
13     protected Context context;
14     
15     public void setContext(Context context){
16         this.context=context;
17     }
18     //电梯的开启门行为
19     public abstract void open();
20     //电梯的关闭们行为
21     public abstract void close();
22     //电梯要能上能下,运行起来的行为
23     public abstract void run();
24     //电梯停下来的行为
25     public abstract void stop();
26 }
View Code

【2】环境角色

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 环境类(上下文类)
 4  * (1)依赖:电梯的状态
 5  * (2)同时具有电梯不同状态的行为,类似代理
 6  * @author sxf
 7  *
 8  */
 9 public class Context {
10 
11     //定义出电梯所有的状态
12     public final static OpenningState openningState=new OpenningState();
13     public final static ClosingState closingState=new ClosingState();
14     public final static RunningState runningState=new RunningState();
15     public final static StoppingState stoppingState=new StoppingState();
16     
17     //定义一个当前的电梯状态
18     private LiftState liftState;
19     
20     public LiftState getLiftState(){
21         return this.liftState;
22     }
23     
24     public void setLiftState(LiftState liftState){
25         this.liftState=liftState;
26         this.liftState.setContext(this);
27     }
28     //开启电梯门
29     public void open(){
30         this.liftState.open();
31     }
32     //关闭电梯门
33     public void close(){
34         this.liftState.close();
35     }
36     //停止电梯
37     public void stop(){
38         this.liftState.stop();
39     }
40     //运行电梯
41     public void run(){
42         this.liftState.run();
43     }
44 }
View Code

【3】电梯开启状态的实现类

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 电梯开启状态
 4  * @author sxf
 5  *
 6  */
 7 public class OpenningState extends LiftState {
 8     
 9 
10     //开启当然可以关闭了
11     @Override
12     public void open() {
13         System.out.println("OpenningState.open(电梯门开启......)");
14     }
15 
16     @Override
17     public void close() {
18         //修改状态
19         super.context.setLiftState(Context.closingState);
20         //动作委托为CloseState来执行
21         super.context.getLiftState().close();
22         
23     }
24 
25     //电梯门若是开着,则不能运行
26     @Override
27     public void run() {
28         //do nothing;
29     }
30     //电梯门是开着,则不能让其停止
31     @Override
32     public void stop() {
33         //do nothing
34     }
35 
36     
37 }
View Code

【4】电梯停止状态的实现类

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 电梯停止的行为
 4  * @author sxf
 5  *
 6  */
 7 public class StoppingState extends LiftState {
 8 
 9     
10 
11     //电梯处于停止状态是可以打开的
12     @Override
13     public void open() {
14         //将电梯的状态设置为打开
15         super.context.setLiftState(Context.openningState);
16         //执行打开的动作
17         super.context.getLiftState().open();
18     }
19 
20     //电梯处于停止状态,门本来就关着
21     @Override
22     public void close() {
23         //do nothing
24     }
25 
26     //电梯处于停止状态,再次运行起来很正常
27     @Override
28     public void run() {
29         //将电梯的状态设置为运行状态
30         super.context.setLiftState(Context.runningState);
31         //执行运行动作
32         super.context.getLiftState().run();
33     }
34 
35     //停止状态要实现的行为
36     @Override
37     public void stop() {
38         System.out.println("StoppingState.stop(电梯停止了.....)");
39     }
40 
41     
42 }
View Code

【5】电梯运行状态的实现类

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 电梯运行时的状态
 4  * @author sxf
 5  *
 6  */
 7 public class RunningState  extends LiftState{
 8 
 9     //运行时,电梯门不允许打开。
10     @Override
11     public void open() {
12         //do nothing
13     }
14     //运行时,电梯门关闭,这是正常的。
15     @Override
16     public void close() {
17         //do nothing
18     }
19 
20     //运行状态下,要实现的行为
21     @Override
22     public void run() {
23         System.out.println("RunningState.run(电梯上下运动.....)");
24     }
25 
26     //这是合理的。运行时,是可以停止的
27     @Override
28     public void stop() {
29         //将电梯的状态设置为停止状态
30         super.context.setLiftState(context.stoppingState);
31         //执行停止的动作
32         super.context.getLiftState().stop();
33     }
34 
35     
36 }
View Code

【6】电梯关闭状态的实现类

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 电梯关闭的状态
 4  * @author sxf
 5  *
 6  */
 7 public class ClosingState extends LiftState {
 8 
 9 
10     //电梯门关了再打开
11     @Override
12     public void open() {
13         //将电梯门的状态该为打开状态
14         super.context.setLiftState(Context.openningState);
15         //执行相应的动作
16         super.context.getLiftState().open();
17     }
18 
19     //电梯们关闭,这是关闭状态要实现的动作
20     @Override
21     public void close() {
22         System.out.println("ClosingState.close(电梯门关闭.....)");
23     }
24 
25     //电梯门关了就运行,这是再正常不过了
26     @Override
27     public void run() {
28         //将电梯门的状态改为运行状态
29         super.context.setLiftState(context.runningState);
30         //执行运行状态的动作
31         super.context.getLiftState().run();
32     }
33 
34     //电梯门关着,我就不按楼层
35     @Override
36     public void stop() {
37         //将电梯门的状态改为停止状态
38         super.context.setLiftState(context.stoppingState);
39         //执行停止动作
40         super.context.getLiftState().stop();
41     }
42 
43     
44 }
View Code

【4】客户端测试

技术分享
 1 package com.yeepay.sxf.template21;
 2 /**
 3  * 客户端测试
 4  * @author sxf
 5  *
 6  */
 7 public class ClientTest {
 8 
 9     public static void main(String[] args) {
10         //初始化上下文环境
11         Context context=new Context();
12         //设置初始化状态
13         context.setLiftState(Context.closingState);
14         //打开门
15         context.open();
16         //运行
17         context.run();
18         //关闭门
19         context.close();
20         //停止门
21         context.stop();
22         
23     }
24 }
View Code

 

设计模式之禅之设计模式-状态模式

标签:

原文地址:http://www.cnblogs.com/shangxiaofei/p/5165386.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!