java设计模式-----22、状态模式
概念:
State模式也叫状态模式,是行为设计模式的一种。State模式允许通过改变对象的内部状态而改变对象的行为,这个对象表现得就好像修改了它的类一样。
根据这个概念,我们举个例子
- public class Behavior {
- private int time;
- public int getTime() {
- return time;
- }
- public void setTime(int time) {
- this.time = time;
- }
- public void eat(){
- if(time == 7){
- System.out.println("吃早饭");
- }else if(time == 12){
- System.out.println("吃午饭");
- }else if(time == 18){
- System.out.println("吃晚饭");
- }else{
- System.out.println("还不到吃饭时间");
- }
- }
- }
- public class MainClass {
- public static void main(String[] args) {
- Behavior behavior = new Behavior();
- behavior.setTime(7);
- behavior.eat();
- behavior.setTime(12);
- behavior.eat();
- behavior.setTime(18);
- behavior.eat();
- behavior.setTime(20);
- behavior.eat();
- }
- }
结果:
可以看到,根据time属性的不同,对象的行为也发生了改变,但是这样的方式很不好,所有的事情都放到了eat()方法中,导致eat()方法过于复杂
下面就看一看状态模式
状态模式的应用场景
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转译到表现不同状态的一系列类当中,可以把复杂的判断逻辑简化。
简单来说:
状态模式的结构
状态模式的角色和职责
1、Context:用户对象:拥有一个State类型的成员,以标识对象的当前状态(Behavior)。
2、State:接口或基类封装与Context的特定状态相关的行为;
3、ConcreteState:接口实现类或子类实现了一个与Context某个状态相关的行为。
按照状态模式,我们来改造一下,刚才的例子,吃早中晚饭,不是吃饭时间,都是状态,所以我们把状态单独封装出来。
首先,新建一个State
- public abstract class State {
- public abstract void eat();
- }
接着新建ConcreteState
- /*
- * 早餐
- */
- public class BreakfastState extends State {
- @Override
- public void eat() {
- System.out.println("吃早餐");
- }
- }
- /*
- * 午餐
- */
- public class LunchState extends State {
- @Override
- public void eat() {
- System.out.println("吃午餐");
- }
- }
- /*
- * 晚餐
- */
- public class DinnerState extends State {
- @Override
- public void eat() {
- System.out.println("吃晚餐");
- }
- }
- /*
- * 不是吃饭时间
- */
- public class NoFoodState extends State {
- @Override
- public void eat() {
- System.out.println("不是吃饭时间");
- }
- }
再修改一下behavior
- public class Behavior {
- private int time;
- State state = null;
- public int getTime() {
- return time;
- }
- public void setTime(int time) {
- this.time = time;
- }
- public void eat(){
- if(time == 7){
- state = new BreakfastState();
- state.eat();
- }else if(time == 12){
- state = new LunchState();
- state.eat();
- }else if(time == 18){
- state = new DinnerState();
- state.eat();
- }else{
- state = new NoFoodState();
- state.eat();
- }
- }
- }
这样,和刚才的结果一样,但是这样子,判断逻辑还是在对象中,我们继续修改,将逻辑写到ConcreteState中
因为,我们要知道time,所以需要向state中传入参数,所以我们将Behavior传进去
- public abstract class State {
- public abstract void eat(Behavior behavior);
- }
然后,修改Behavior
- public class Behavior {
- private int time;
- State state = null;
- public Behavior() {
- state = new BreakfastState();
- }
- public int getTime() {
- return time;
- }
- public void setTime(int time) {
- this.time = time;
- }
- public State getState() {
- return state;
- }
- public void setState(State state) {
- this.state = state;
- }
- public void eat(){
- //逻辑取出,所以这里只剩调用方法
- state.eat(this);
- //当所有方法都完成后,回到最初始状态
- state = new BreakfastState();
- }
- }
接着,再继续修改每一个ConcreteState
- /*
- * 早餐
- */
- public class BreakfastState extends State {
- @Override
- public void eat(Behavior behavior) {
- if(behavior.getTime() == 7){
- System.out.println("吃早餐");
- }else{
- //如果不符合条件,重置state为下一个状态
- behavior.setState(new LunchState());
- behavior.eat();
- }
- }
- }
- /*
- * 午餐
- */
- public class LunchState extends State {
- @Override
- public void eat(Behavior behavior) {
- if(behavior.getTime() == 12){
- System.out.println("吃午餐");
- }else{
- behavior.setState(new DinnerState());
- behavior.eat();
- }
- }
- }
- /*
- * 晚餐
- */
- public class DinnerState extends State {
- @Override
- public void eat(Behavior behavior) {
- if(behavior.getTime() == 18){
- System.out.println("吃晚餐");
- }else{
- behavior.setState(new NoFoodState());
- behavior.eat();
- }
- }
- }
- /*
- * 不是吃饭时间
- */
- public class NoFoodState extends State {
- @Override
- public void eat(Behavior behavior) {
- System.out.println("不是吃饭时间");
- }
- }
这样,结果和之前是一样的
状态模式的优点与缺点
优点: 1、封装了转换规则。
2、枚举可能的状态,在枚举状态之前需要确定状态种类。
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点: 1、状态模式的使用必然会增加系统类和对象的个数。
2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
java设计模式-----22、状态模式的更多相关文章
- 折腾Java设计模式之状态模式
原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...
- JAVA设计模式--State(状态模式)
状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...
- JAVA设计模式:状态模式
声明:转载请说明来源:http://www.cnblogs.com/pony1223/p/7518226.html 一.引出状态模式 假设我们现在有一个糖果机项目,那么我们知道正常一般糖果机提供给用户 ...
- Java设计模式之状态模式详解
(本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑.且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见.<设计模式之禅> ...
- java设计模式之状态模式
状态模式 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 状态模式UML图 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关 ...
- 曾侯乙编钟引发的遐想之Java设计模式:状态模式
目录 示例 简单例子 改进代码 状态模式 定义 意图 主要解决问题 何时使用 优缺点 曾侯乙编钟 状态模式-命令模式-策略模式 示例 一个类对外提供了多个行为,同时该类对象有多种状态,不同状态下对外的 ...
- 乐在其中设计模式(C#) - 状态模式(State Pattern)
原文:乐在其中设计模式(C#) - 状态模式(State Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 状态模式(State Pattern) 作者:webabcd 介绍 允 ...
- 折腾Java设计模式之备忘录模式
原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...
- 折腾Java设计模式之访问者模式
博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...
- 折腾Java设计模式之命令模式
博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...
随机推荐
- 【BZOJ3709】 [PA2014]Bohater(贪心)
传送门 BZOJ Solution 考虑如果可以回血肯定要打,那么就是按照伤害值从小到大排个序能打就打,不能打就\(NIE\). 接着看不能够回血的,emmm,把这个过程反着看一下就是打一个怪扣\(a ...
- 【062新题】OCP 12c 062出现大量新题-15
choose one In your Oracle 12c database, you plan to execute the command: SQL> CREATE TABLESPACE t ...
- JFrame、JPanel 、Layout开发的简单例子
写了Java这么久,居然发现想手写一个带网格袋布局的JFrame,还不记得怎么写,写了这么多代码真不敢说记得所有细节. 幸好,只要记清楚概念就能快速开发.首先,明确一下3种容器类的差别和用途: No. ...
- python iter函数用法
iter函数用法简述 Python 3中关于iter(object[, sentinel)]方法有两个参数. 使用iter(object)这种形式比较常见. iter(object, sentinel ...
- odoo 开发基础 -- 视图之widget
Odoo 中的widget many2many_tags one2many_list selection progressbar selection statusbar handle monetary ...
- 利用Warensoft Stock Service编写高频交易软件--DEMO
利用Warensoft Stock Service编写高频交易软件 无论是哪种交易软件,对于程序员来讲,最麻烦的就是去实现各种算法.本文以SAR算法的实现过程为例,为大家说明如何使用Warensoft ...
- EFCore.MySql当模型遇到int[]怎么办
我使用的是Pomole.EntityFrameworkCore.MySql 需要将旧项目中的excels表转成实体,其中有一列是json格式的int[] 当遇到第一张表的时候,我使用了这样的方法来读取 ...
- Facade外观模式(结构性模式)
1.系统的复杂度 需求:开发一个坦克模拟系统用于模拟坦克车在各种作战环境中的行为,其中坦克系统由引擎.控制器.车轮等各子系统构成.然后由对应的子系统调用. 常规的设计如下: #region 坦克系统组 ...
- RandomStringUtils工具类
//产生5位长度的随机字符串,中文环境下是乱码 RandomStringUtils.random(5); //使用指定的字符生成5位长度的随机字符串 RandomStringUtils.random( ...
- JVM Scan
1.jmap -histo pid|head -100 2.jstat -gcutil pid cycle 3.jmap -heap pid