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 }
运行结果如下:
开机啦
下一个频道
调高音量
关机啦
果然,状态改变时,行为也跟着改变了。
转载于:https://www.cnblogs.com/start1225/p/6736188.html
7 行为型模式之 - 状态模式相关推荐
- 行为型模式之 状态模式
状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类.其别名为状态对象(Objects for States),状态模式是一种对象行为型模式 ...
- Java进阶篇设计模式之十二 ---- 备忘录模式和状态模式
前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...
- 设计模式之模板方法模式、策略模式、命令模式、责任链模式、状态模式
前言 本章节给您介绍23种设计模式的行为型模式中的模板方法模式.策略模式.命令模式.责任链模式.状态模式. 如有帮助记得3连 加 关注哦!欢迎品论去留言交流,谢谢阅读! 文章目录 前言 一.模板方法模 ...
- 【设计模式】 模式PK:策略模式VS状态模式
1.概述 行为类设计模式中,状态模式和策略模式是亲兄弟,两者非常相似,我们先看看两者的通用类图,把两者放在一起比较一下. 策略模式(左)和状态模式(右)的通用类图. 两个类图非常相似,都是通过Cont ...
- Java设计模式之策略模式与状态模式
一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. 好了,定义看看就完了,我知道你很烦看定义. 二.策 ...
- java - 策略模式、状态模式、卫语句,避免多重if-else(转)
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- 《大话》之 策略模式 Vs 状态模式
一.简介: 策略模式: 背景:商店要打折销售,各种版本的销售方式,让小菜心烦意乱 内容: 定义算法家族,分别封装起来,让他们之间可以户型替换,此模式让算法的变化,不会影响到使用算法的用户. 图文 ...
- Java 策略模式和状态模式
本文是转载的,转载地址:大白话解释Strategy模式和State模式的区别 先上图: 本质上讲,策略模式和状态模式做得是同一件事:去耦合.怎么去耦合?就是把干什么(语境类)和怎么干(策略接口)分开, ...
- java输出不同颜色_Java设计模式-策略模式、状态模式
推荐阅读: 一只Tom猫:都是"Redis惹的祸",害我差点挂在美团三面,真是"虚惊一场"! java喵:6大面试技能树:JAVA基础+JVM+算法+数据库+计 ...
- 对策略模式与状态模式的一点思考
在以前的一片博文里 http://www.cnblogs.com/mightofcode/archive/2012/11/19/2771216.html,我发表了我对设计模式的一点看法 但是今天的一个 ...
最新文章
- SAP QM QS41 试图维护Catalog为3的Code Group, 报错-You need to maintain catalog 3 (Usage Decisions) in Customi
- 团队-石头剪刀布-模块测试过程
- Nancy之结合tinyfox给我们的应用提供简单的数据服务
- OpenBFDD的安装与使用
- 加载不同linux内核,Linux内核加载过程
- mysql删除emp表的语句_MySQL删除数据表(DORP TABLE语句)
- centos下安装mysql5.5_CentOS下安装Mysql5.5
- JAVA操作文件大全(二)
- Python3.7.2版本出现ModuleNotFoundError: No module named 'paramiko'解决办法
- 安装与配置OCS服务器时可能会出现的问题
- 用Tensorflow求逆矩阵
- 恒生校招java笔试数据库语法_2015恒生电子校招笔试详解
- OpenGL学习(六)纹理与obj格式模型的读取
- STM32+Zigbee模块实现串口通信获取传感器数据
- java拼接字符串返回
- bluehost 盗版_如何免费使用bluehost设置电子邮件地址并连接到gmail或Outlook 2020
- 卡特加特数字家庭又爆重磅合作!厦门火炬创投莅临卡特加特考察
- Java文件完整性校验SHA256
- 梦江湖获取服务器信息,《一梦江湖》6月5日更新公告
- 穿越时间的蛀洞——书评《Java企业设计模式》
热门文章
- pku3277 City Horizon.(离散化+二分查找)
- ubuntu16.04中 启动 Error starting userland proxy: listen tcp 0.0.0.0:5900: bind: address already in use
- 正确使用auto_ptr智能指针
- 聚焦改变字体,背景颜色
- CLR via C# ver4.0 读书笔记
- [转]IE首页被http://www.9798.net/篡改解决办法
- 在sqlserver sql语句中查找速度快
- break、continue
- java继承,final,super,Object类,toString,equals,
- meta 标签的作用