7 行为型模式之

摘要:
状态模式的行为是平行的,而不可替代的策略模式的行为则是独立的,可以用一句话来表达。状态模式封装了不同状态类中对象的行为,每个状态对象都有一个公共的抽象状态基类。频道切换和音量调整是行为。状态的改变是否会影响行为,这也与上述状态模式的介绍一致。

状态模式的介绍:(重点就在这句)状态模式中的行为是由状态来决定的,不同的状态下有不同的行为。

状态模式和策略模式的结构几乎是一样的,但是他们的目的,本质却完全不一样。

状态模式的行为是平行的,不可替换的

策略模式的行为是独立的,可以相互替换的

用一句话来表述,状态模式把对象的行为封装在不同的状态类中,每一个状态对象(状态类的实例)都有一个共同的抽象状态基类。

状态模式的意图是让一个对象在其内部状态改变时,其行为也随之改变

状态模式的定义:当一个对象的内部状态发生改变时允许其改变行为

状态模式使用场景:(下面两个场景很重要)

(1)一个对象的行为取决于它的状态,并且它必须在运行时根据状态来改变其行为

(2)代码中把包含大量与对象状态有关的条件语句,例如,一个操作中含有庞大的多分支语句 if else 或者 switch case ,且这些分支依赖于该对象的状态

状态模式是将每一个条件分支放入一个独立的类中,这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化,

这样通过多态来去除过多的,重复的if else 等分支语句

下面就以电视遥控器为例来演示一下状态模式的实现。我们首先将电视的状态简单分为开机状态和关机状态,在开机状态下,可以通过遥控器进行频道切换,调整音量等操作,但是,此时重复按开机键是无效的,而在关机状态下,频道切换,音量操作是无效的操作,只有按开机按钮时会生效,也就是说电视的内部状态决定了遥控器的行为。

结合上面的状态模式的定义:开机和关机就是所说的状态。频道切换和调整音量操作就是行为。状态能影响行为,和使用的场景(1)是可以对得上了。

状态改变,其行为也会改变,例如电视开机状态下,是可以把音量调大或者调小的,如果此时电视机状态变为关机了,音量就不可以调了。是不是状态改变了就可以影响到了行为了,这和上面的状态模式的介绍也可以对得上了。

是的,状态模式就是这样一个模式,行为受状态的影响。和策略模式有点像,但是要记得,是有本质区别的。

以上面的例子,看一下第一版的实现。

 1 /**
 2  *
 3  * 电视遥控器,含有开机,关机,下一频道,上一频道,调高音量,调低音量
 4  */
 5 public class TvController {
 6     //开机状态
 7     private final static int POWER_ON   = 1;
 8     //关机状态
 9     private final static int POWER_OFF  = 2;
10     private int mState = POWER_OFF;
11 
12     //开机
13     public void powerOn(){
14         mState = POWER_ON;
15         if(mState == POWER_OFF){
16             System.out.println("开机啦");
17         }
18     }
19 
20 
21     //关机
22     public void powerOff(){
23         mState = POWER_OFF;
24         if(mState == POWER_ON){
25             System.out.println("关机啦");
26         }
27     }
28 
29     //下一频道
30     public void nextChannel(){
31         if(mState == POWER_ON){
32             System.out.println("下一频道");
33         }else {
34             System.out.println("两个红灯提示没有开机");
35         }
36     }
37 
38     //上一频道
39     public void preChannel(){
40         if(mState == POWER_ON){
41             System.out.println("上一频道");
42         }else {
43             System.out.println("两个红灯提示没有开机");
44         }
45     }
46 
47     //调高音量
48     public void turnUp(){
49         if(mState == POWER_ON){
50             System.out.println("调高音量");
51         }else {
52             System.out.println("两个红灯提示没有开机");
53         }
54     }
55 
56     //调低音量
57     public void turnDown(){
58         if(mState == POWER_ON){
59             System.out.println("调低音量");
60         }else {
61             System.out.println("两个红灯提示没有开机");
62         }
63     }
64 
65 
66 }

可以看到,在TvController类中,通过mState字段存储了电视的状态,并且在各个操作中根据状态来判断是否应该执行。这就导致了在每个功能中都需要使用if else,代码重复,相对较为混乱,这是在只有两个状态和几个简单的功能函数的情况下,如果状态变成5个,10个呢?每个函数都要有if else 判断,而这些代码都充斥在一个类中,这些重复的代码无法被提取出来,这使得这个类变得越来越难以维护。

  状态模式就是为这类问题而出现的,我们将这些状态用状态对象来代替,将这些行为封装在状态类中,使得在不同的状态下有不同的实现,这样就将这些if else 从

TvController类中去掉,整个结构也简单变得清楚起来,我们看看实现的代码:

1 /**
2  * 电视状态接口,定义了电视操作的函数
3  */
4 public interface TvState {
5     void nextChannel();     //下一个频道
6     void preChannel();      //上一个频道 
7     void turnUp();          //调高音量
8     void turnDown();        //调低音量
9 }

开机状态

 1 /**
 2  * 开机状态
 3  */
 4 public class PowerOnState implements TvState{
 5     @Override
 6     public void nextChannel() {
 7         System.out.println("下一个频道");
 8     }
 9 
10     @Override
11     public void preChannel() {
12         System.out.println("上一个频道");
13     }
14 
15     @Override
16     public void turnUp() {
17         System.out.println("调高音量");
18     }
19 
20     @Override
21     public void turnDown() {
22         System.out.println("调低音量");
23     }
24 }

关机状态

 1 /**
 2  * 关机状态
 3  */
 4 public class PowerOffState implements TvState{
 5     @Override
 6     public void nextChannel() {
 7 
 8     }
 9 
10     @Override
11     public void preChannel() {
12 
13     }
14 
15     @Override
16     public void turnUp() {
17 
18     }
19 
20     @Override
21     public void turnDown() {
22 
23     }
24 }

电源操作接口

1 /**
2  * 电源操作接口
3  */
4 public interface PowerControl {
5     void powerOn();
6     void powerOff();
7 }

电视遥控器

 1 /**
 2  * 遥控器
 3  */
 4 public class TvControl implements PowerControl{
 5     TvState mState;
 6 
 7     public void setState(TvState state){
 8         mState = state;
 9     }
10 
11     //改变为开机状态
12     @Override
13     public void powerOn() {
14         //改变为开机状态,把状态设置为开机状态
15         setState(new PowerOnState());
16         System.out.println("开机啦");
17     }
18 
19     //改变为关机状态
20     @Override
21     public void powerOff() {
22         //改变为关机状态,把状态设置为开机状态
23         setState(new PowerOffState());
24         System.out.println("关机啦");
25     }
26 
27     public void nextChannel(){
28         mState.nextChannel();
29     }
30 
31     public void preChannel(){
32         mState.preChannel();
33     }
34 
35     public void turnUp(){
36         mState.turnUp();
37     }
38 
39     public void turnDown(){
40         mState.turnDown();
41     }
42 
43 }

下面是客户端测试类

 1 /**
 2  * 客户端测试类
 3  */
 4 public class StateTest {
 5 
 6     public static void main(String[] args){
 7         test();
 8     }
 9 
10 
11     public static void test(){
12         //电视
13         TvControl tvControl = new TvControl();
14         //改变状态,看看是否影响行为
15         tvControl.powerOn();
16         //下一个频道
17         tvControl.nextChannel();
18         //调大音量
19         tvControl.turnUp();
20         //设置关机状态
21         tvControl.powerOff();
22         //调高音量,此时不会生效
23         tvControl.turnUp();
24     }
25 }

运行结果如下:

开机啦
下一个频道
调高音量
关机啦

果然,状态改变时,行为也跟着改变了。

欢迎访问作者的helloworld的个人博客:
https://www.helloworld.net/jiulu

同时也可以加作者的微信:daitukeji
也可以扫下面的二维码添加
![image](https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/f0b62fd75da7cbeba3b77965f4e26845.png)

免责声明:文章转载自《7 行为型模式之》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇前端工程师必须要知道的SEO技巧(1):rel=nofollow的使用subline注册码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Strategy(策略)模式

1.概述         在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将...

C#设计模式总结(转)

一、引言   经过这段时间对设计模式的学习,自己的感触还是很多的,因为我现在在写代码的时候,经常会想想这里能不能用什么设计模式来进行重构。所以,学完设计模式之后,感觉它会慢慢地影响到你写代码的思维方式。这里对设计模式做一个总结,一来可以对所有设计模式进行一个梳理,二来可以做一个索引来帮助大家收藏。   PS: 其实,很早之前我就看过所有的设计模式了,但是...

Java 设计模式六原则及23中常用设计模式

一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访...

Java设计模式之状态模式详解

(本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑、且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见。《设计模式之禅》这本书中对状态模式有着非常详尽的讲解(目前为止我认为讲解得最好的书),但总觉得自己没能够理解透彻、灵活运用。直到今年完成了一个通信协议软件的开发,重新研究了“状态机”,...

c#中的23种设计模式

C# 23种设计模式汇总 创建型模式 工厂方法(Factory Method) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节。工厂方法模式的核心是一个抽象工厂类,各种具体工厂类通过抽象工厂类将工厂方法继承下来。如此使得客户可以只关心抽象产品和抽象工厂,完全不用理会返回的是哪一种具体产品,也不用...

设计模式学习(22)- 状态模式

状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的。 这种类型的设计模式属于行为型模式。 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。 TS实现: 总结: 1、有一个 状态机(老师) ,然后每种状态由单独的“状态类”去实现。 2、状态机(老师)的行为受状态类的影响。...