行为型模式之 状态模式
状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。
如何解决:将各种具体的状态类抽象出来。
关键代码:通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if...else 等条件选择语句。
优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点: 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
使用场景: 1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。
注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
实现
我们将创建一个 State 接口和实现了 State 接口的实体状态类。Context 是一个带有某个状态的类。
//步骤1 创建一个接口 class State { public:void virtual doAction(Context* context) {}virtual string ToString() { return ""; } };//步骤二 创建context类 class Context { private:State* state;public:Context() {state = NULL;}void SetState(State* stat) {state = stat;}State* GetState() {return state;} };//步骤二 创建接口实体类 class startState :public State { public:void doAction(Context* context){cout << "start state" << endl;context->SetState(this);}string ToString() { return "Start state"; } };class stopState :public State { public:void doAction(Context* context){cout << "stop state" << endl;context->SetState(this);}string ToString() { return "Stop state"; } };int main() {Context cont;startState startstat;startstat.doAction(&cont);cout << cont.GetState()->ToString() << endl;stopState stopstat;stopstat.doAction(&cont);cout << cont.GetState()->ToString() << endl;return 0; }
模式分析:
- 状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为。
- 状态模式的关键是引入了一个抽象类来专门表示对象的状态,这个类我们叫做抽象状态类,而对象的每一种具体状态类都继承了该类,并在不同具体状态类中实现了不同状态的行为,包括各种状态之间的转换。
在状态模式结构中需要理解环境类与抽象状态类的作用:
- 环境类实际上就是拥有状态的对象,环境类有时候可以充当状态管理器(State Manager)的角色,可以在环境类中对状态进行切换操作。
- 抽象状态类可以是抽象类,也可以是接口,不同状态类就是继承这个父类的不同子类,状态类的产生是由于环境类存在多个状态,同时还满足两个条件: 这些状态经常需要切换,在不同的状态下对象的行为不同。因此可以将不同对象下的行为单独提取出来封装在具体的状态类中,使得环境类对象在其内部状态改变时可以改变它的行为,对象看起来似乎修改了它的类,而实际上是由于切换到不同的具体状态类实现的。由于环境类可以设置为任一具体状态类,因此它针对抽象状态类进行编程,在程序运行时可以将任一具体状态类的对象设置到环境类中,从而使得环境类可以改变内部状态,并且改变行为。
总结:
- 状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象,状态模式是一种对象行为型模式。
- 状态模式包含三个角色:环境类又称为上下文类,它是拥有状态的对象,在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象,可以定义初始状态;抽象状态类用于定义一个接口以封装与环境类的一个特定状态相关的行为;具体状态类是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。
- 状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为。
- 状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。
- 状态模式适用情况包括:对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为;代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。
转载于:https://www.cnblogs.com/gardenofhu/p/8508743.html
行为型模式之 状态模式相关推荐
- 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,我发表了我对设计模式的一点看法 但是今天的一个 ...
最新文章
- 数字下变频和数字上变频
- python IO多路复用源码
- leetcode 最后一个单词的长度
- 如何编译文件(gcc + nasm)
- 前端学习(100):float注意点整理1
- php set_timeout,和 JS 一样的 php setTimeout 函数
- mysql设置catalog_Catalog与Schema
- Java中Math3 各种随机数生成器的使用(Random Generator)
- mysql in 通配符_mysql必知必会--用通配符进行过滤
- leetcode先刷_Maximum Subarray
- MongoDB从入门到高级的实战操作
- 图扑软件 | 数字孪生智慧选煤厂
- iOS开发 手势密码解锁和指纹TouchID解锁
- QQ秀文字,很酷的!
- 如何查看软件是32位还是64位
- 获取晋江优质小说(按章节数量选择、python多进程)
- Pytorch版本过高产生的RuntimeError: Legacy autograd function with non-static forward method is deprecated.
- Python实用脚本实践
- IDC数据中心机房气体灭火系统知识
- 25【中介者设计模式】
热门文章
- org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result
- Java二叉搜索树转循环链表,关于java:二叉搜索树转换为单向链表interview1712
- 从本地push到github以及从github拉一个项目,以及克隆
- docker使用之私有仓库构建(四)
- 路由协议管理距离汇总
- 非官方构建的 Windows 下的 Atom 编辑器
- SQL表操作习题4 14~25题 缺20题
- javaSE学习 访问控制
- 给原型扩展一下tirm方法
- 2008Server错误