状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类

考虑如下场景,自动售票机:

每一个方格表示自动售票机的一种状态,每一个箭头线表示自动售票机由一个状态转换到另一个状态所需要的操作

状态抽象为自动售票机类的参数,操作抽象为自动售票机类的方法

创建一个实例变量持有状态值,方法内增加条件代码处理不同状态

public class TVM { final static int noCoin = 1;final static int hasCoin = 2;final static int ticketOut = 3;private int state = noCoin;public void insertCoin(){if(state == noCoin){this.state = hasCoin;System.out.println("Insert a coin!");}else if(state == hasCoin){System.out.println("You have already inserted a coin!");}else{System.out.println("The ticket is out,please wait!");}}public void cancel(){if(state == noCoin){System.out.println("You do not insert a coin!");}else if(state == hasCoin){this.state = noCoin;System.out.println("Give the coin back to you!");}else{System.out.println("The ticket is out,can not cancel!");}}public void confirm(){if(state == noCoin){System.out.println("You do not insert a coin!");}else if(state == hasCoin){this.state = ticketOut;System.out.println("Ticket out!");}else{System.out.println("The ticket is out,can not confirm!");}}public void getTicket(){if(state == noCoin){System.out.println("There is not ticket to get!");}else if(state == hasCoin){System.out.println("There is not ticket to get!");}else{this.state = noCoin;System.out.println("Waiting for another passenger!");}}
}
public class Passenger {public static void main(String[] args) {TVM m = new TVM();m.insertCoin();m.cancel();m.insertCoin();m.confirm();m.getTicket();}
}

结果:

Insert a coin!
Give the coin back to you!
Insert a coin!
Ticket out!
Waiting for another passenger!

当初设计的时候并没有考虑电子票会售完这个问题,现在要弥补这个错误:

按照之前的设计方式:

1,状态代码混杂于自动售票机类中,新增加一个“售罄”的状态,则自动售票机类就需进行大量修改,即状态的变更总会导致售票机类的修改

2,不同状态的代码混杂在一起,大量的if/else,极容易出错

根据“封装可变性”的设计原则,将可变的“状态”进行封装,以实现具体状态代码与售票机类之间的解耦

public interface Status {public void insertCoin();public void cancel();public void confirm();public void getTicket();
}
public class NoCoin implements Status {private TVM tvm;public NoCoin(TVM tvm){this.tvm = tvm;}public void insertCoin() {tvm.setStatus(tvm.getHasCoin());System.out.println("Insert a coin!");}public void cancel() {System.out.println("You do not insert a coin!");}public void confirm() {System.out.println("You do not insert a coin!");}public void getTicket() {System.out.println("There is not ticket to get!");}
}
public class HasCoin implements Status {private TVM tvm;public HasCoin(TVM tvm){this.tvm = tvm;}public void insertCoin() {System.out.println("You have already inserted a coin!");}public void cancel() {tvm.setStatus(tvm.getNoCoin());System.out.println("Give the coin back to you!");}public void confirm() {tvm.setStatus(tvm.getTicketOut());System.out.println("Ticket out!");}public void getTicket() {System.out.println("There is not ticket to get!");}
}
public class TicketOut implements Status {private TVM tvm;public TicketOut(TVM tvm){this.tvm = tvm;}public void insertCoin() {System.out.println("The ticket is out,please wait!");}public void cancel() {System.out.println("The ticket is out,can not cancel!");}public void confirm() {System.out.println("The ticket is out,can not confirm!");}public void getTicket() {if(tvm.getNum() > 0){tvm.setNum(tvm.getNum() - 1);tvm.setStatus(tvm.getNoCoin());System.out.println("Waiting for another passenger!");}else{tvm.setStatus(tvm.getSoldOut());System.out.println("Sold out!");}}
}
public class SoldOut implements Status {private TVM tvm;public SoldOut(TVM tvm){this.tvm = tvm;}public void insertCoin() {System.out.println("Sold out,can not insert coin!");}public void cancel() {System.out.println("Sold out,can not cancel!");}public void confirm() {System.out.println("Sold out,can not confirm!");}public void getTicket() {System.out.println("Sold out,can not get ticket!");}
}
public class TVM {private NoCoin noCoin;private HasCoin hasCoin;private TicketOut ticketOut;private SoldOut soldOut;private Status status;private int num;public TVM(){noCoin = new NoCoin(this);hasCoin = new HasCoin(this);ticketOut = new TicketOut(this);soldOut = new SoldOut(this);status = noCoin;num = 1;}public void insertCoin(){status.insertCoin();}public void cancel(){status.cancel();}public void confirm(){status.confirm();}public void getTicket(){status.getTicket();}public void setStatus(Status status){this.status = status;}public Status getNoCoin(){return noCoin;}public Status getHasCoin(){return hasCoin;}public Status getTicketOut(){return ticketOut;}public Status getSoldOut(){return soldOut;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}
}

我们来测试一下:

public class Passenger {public static void main(String[] args) {TVM m = new TVM();m.insertCoin();m.cancel();m.insertCoin();m.confirm();m.getTicket();m.insertCoin();m.confirm();m.getTicket();m.insertCoin();}
}
Insert a coin!
Give the coin back to you!
Insert a coin!
Ticket out!
Waiting for another passenger!
Insert a coin!
Ticket out!
Sold out!
Sold out,can not insert coin!

通过这个设计也可以看到,自动售票机类对修改关闭,状态类对扩展开放

经过重新设计,类的数量急剧增多,这是为了获得扩展性而付出的代价,其实真正重要的是暴漏给用户的类的数量

作为自动售票机的内部状态,用户没有必要知道其细节,我们也有能力将其隐藏,比起大块的if/else语句,代码也更容易理解与维护,利大于弊

看一下状态模式的类图,是不是和第二种设计一模一样:

PS:

状态模式和策略模式从类图上来看没有区别,本质上真的有什么区别么?

策略模式:除非告诉对象使用另一个策略,否则对象会一直使用其初始化时被赋予的策略

继承的一种替代方式

状态模式:初始化时告诉类从哪个状态开始,随着时间的变化,状态也会自动发生变化

大量条件判断语句的替代方式

转载于:https://www.cnblogs.com/sean-zou/p/3710036.html

状态模式(State Pattern)相关推荐

  1. php 状态模式,PHP设计模式(十九)—状态模式 (State Pattern)

    状态模式 (State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类.其别名为状态对象(Objects for States) (一)为什么需要状态模式 ...

  2. 设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)

    说到状态模式,如果你看过之前发布的重构系列的文章中的<代码重构(六):代码重构完整案例>这篇博客的话,那么你应该对"状态模式"并不陌生,因为我们之前使用到了状态模式进行 ...

  3. 极速理解设计模式系列:22.状态模式(State Pattern)

    四个角色:抽象状态类(State).具体状态类(ConcreateState).情景类(Context).客户端(Client) 抽象状态类(State):提供一个与情景类有关的State行为. 具体 ...

  4. 41状态模式(State Pattern)

    对象状态影响对象行为:     对象拥有不同的状态,往往会行使不同的行为...                     动机:     在软件构建过程中,某些对象的状态如果改变以及其行为也会随之而发生 ...

  5. c++状态模式state

    c++状态模式state 概念 角色和职责 案例 概念 State模式也叫状态模式,是行为设计模式的一种.State模式允许通过改变对象的内部状态而改变对象的行为,这个对象表现得就好像修改了它的类一样 ...

  6. 【转】设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  7. 状态模式(State)-七十二变

    状态模式(State)-老孙七十二变 俺老孙来也-我是如来佛祖玉皇大帝观音菩萨指定取西经特派使者花果山水帘洞美猴王齐天大圣孙悟空啊!老孙的必杀技就是七十二变,没错比老外的变相怪杰还有牛逼许多. 关于老 ...

  8. 读书笔记_java设计模式深入研究 第八章 状态模式 State

    1,状态模式:事务有n个状态,且维护状态变化. 2,UML模型: -1,上下文环境Context:定义客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete   ...

  9. 设计模式之状态模式(State)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

最新文章

  1. [翻译]Python中yield的解释
  2. c++ 代码_C代码对汇编代码中声明的全局符号的访问方式详解
  3. Java StringBuffer类
  4. 查询已有链表的hashmap_原创 | 面试不再慌,看完这篇保证让你写HashMap跟玩一样...
  5. Qt笔记-Linux程序控制台启动界面实例
  6. centos/linux下的安装Nginx
  7. 无键盘屏幕配置树莓派连接WiFi
  8. kafka zookeeper docker容器互联
  9. python高阶知识之——列表推导式(63)
  10. man手册中文版设置
  11. 搞了三天终于成功跑起来GitHub上的vue-element-admin最新解决办法!(mac系统亲测有效)
  12. 区块链 Hyperledger Composer 使用教程(环境搭建、项目开发 一)
  13. Android 查询设备信息c/c++常用方法
  14. extract($_POST, EXTR_SKIP)讲解
  15. python如何实现隔行换色_Excel2010如何实现隔行设置背景色
  16. 3U VPX T2080通信处理板卡
  17. 码农+码农=码农 ?
  18. FPGA error:buffers of the same direction cannot be placed in series.
  19. BuildAdmin后台管理系统入门分析:01
  20. YOLO&Deepsort的车速&车流量检测系统(源码&部署教程)

热门文章

  1. 北邮人工智能学院刘勇教授实验室,招聘博士后研究人员
  2. 多目标跟踪新范式:CenterTrack
  3. 2021 年软件工程现状:Python 或将成为第一大编程语言,中国开源涨势最猛
  4. linux系统挂载磁盘慢,arch开机速度竟然是挂载磁盘拖慢了。。
  5. 22课时、19大主题,CS 231n进阶版课程视频上线!
  6. 安装程序将在重启您的计算机后黑屏,安装windows10一直黑屏怎么解决_win10安装到一半黑屏修复方法...
  7. 一个会“说话”的油箱盖,告诉你每一滴油的去向
  8. 微信监控机器学习、深度学习训练过程,可视化
  9. php+js实现异步图片上传,JavaScript实现异步图像上传功能
  10. smb 限制大文件上传_单个文件大小 上传百度云盘 微信发送 有大小限制 怎么破?...