状态模式——HeadFirst设计模式学习笔记

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

——将状态封装成独立的类,将动作委托给当前状态对象,所以行为会随着内部状态的变化而变化

状态转换图:为每一个状态创建一个实现一组相同操作接口的对象,实体对象包含所有状态并有一个当前状态接口的引用

特点:

  • 允许一个对象基于不用的状态有不同的行为
  • 把变化的东西取出来,局部化每个状态的行为,每个状态的行为局部化到自己的类中,遵守“封装变化”原则,减少了繁琐的if语句,满足“对修改关闭,对扩展开放”原则,便于阅读与理解
  • 所有的状态实现共同的state接口,state接口可以作为抽象类,减少代码冗余,默认实现可以作为不支持操作
  • 实体对象包含它的每一个状态,当前状态总是这些状态之一,当动作被调用时,它会把动作委派给当前的状态完成

注意:

  • 状态的转换可以在Context中实现(状态转换是固定的),亦可在具体的状态类中实现(状态转化是动态的,状态类之间产生了依赖)
  • 客户不可以直接改变Context中的状态
  • 状态可以被共享
  • 明确主机的行为与主机的状态的之间的关系,主机的某种状态的操作可以操作主机的行为。例:

状态模式vs策略模式: 

  • 均允许对象通过组合和委托拥有不同的行为或算法
  • 状态模式的的当前状态游走于对象的状态集合之间,状态的改变是有方案的,客户不了解状态变化的方式;策略模式客户主动指定状态中的哪一个

举例:

实现糖果自动贩卖机过程,状态转换图如上 

状态接口及SoldState实现:

 1 public interface State {
 2    public void insertQuarter();   // 投入25分钱
 3    public void ejectQuarter();    // 拒绝25分钱
 4    public void turnCrank();       // 转动曲柄
 5    public void dispense();        // 发放糖果
 6 }
 7
 8
 9 public class SoldState implements State{
10
11     GumballMachine gumballMachine;
12     public SoldState(GumballMachine gumballMachine) {
13         this.gumballMachine = gumballMachine;
14     }
15     // 投入25分钱
16     public void insertQuarter() {
17         System.out.println("Please wait, we‘re already giving you a gumball");
18     }
19     // 拒绝25分钱
20     public void ejectQuarter() {
21         System.out.println("Sorry,you have already turn crank");
22     }
23     // 转动曲柄
24     public void turnCrank() {
25         System.out.println("trun twice ,doesn‘t give you anthor gamball!");
26     }
27     // 发放糖果
28     public void dispense() {
29         gumballMachine.releaseBall();
30         if(gumballMachine.getCount()>0){
31             gumballMachine.setState(gumballMachine.getNoQuarterState());
32         } else {
33             System.out.println("Opps,out of gamball!");
34             gumballMachine.setState(gumballMachine.getSoldOutState());
35         }
36     }
37 } 

自动贩卖机实现:

 1 public class GumballMachine {
 2     //状态实例
 3     State soldOutState;
 4     State noQuarterState;
 5     State hasQuarterState;
 6     State soldState;
 7     State winnerState;
 8
 9     // 实例变量state,初始化为糖果售罄状态
10     State state = soldOutState;
11     // 记录机器内装有糖果的数目,开始机器是没有装糖果的
12     int count=0;
13     // 构造器取得糖果的初始数目并把它放在一个实例变量count中
14     public GumballMachine(int numberGumballs) {
15         // 每种状态都创建一个状态实例
16         soldOutState=new SoldOutState(this);
17         noQuarterState=new NoQuarterState(this);
18         hasQuarterState=new HasQuarterState(this);
19         soldState=new SoldState(this);
20         winnerState = new WinnerState(this);
21
22         this.count = numberGumballs;
23         // 若超过0颗糖果,就将状态设置为NoQuarterState
24         if(numberGumballs > 0) {
25             state = noQuarterState;
26         }
27     }
28     // 取得机器内的糖果数目
29     public int getCount() {
30         return count;
31     }
32     // 取得糖果售罄状态
33    // ……
34
35     // 投入25分钱
36     public void insertQuarter(){
37         state.insertQuarter();
38     }
39     // 拒绝25分钱
40     public void ejectQuarter(){
41         state.ejectQuarter();
42     }
43     // 转动曲柄
44     public void turnCrank(){
45         state.turnCrank();
46         state.dispense();
47     }
48     // 设置状态
49     public void setState(State state){
50         this.state=state;
51     }
52     // 糖果滚出来一个
53     public void releaseBall(){
54         System.out.println("A gumball comes rolling out of the solt...");
55         if(count!=0){
56             count--;
57         }
58     }
59 }  
时间: 2024-10-16 16:03:02

状态模式——HeadFirst设计模式学习笔记的相关文章

中介者模式——HeadFirst设计模式学习笔记

中介者模式:集中管理相关对象之间的复杂沟通和控制     ------>>>>    特点: 关系复杂的对象之间解耦了(对象之间必须相互认识 -> 对象只认识中介者) 中介者包含了整个系统的控制逻辑,控制逻辑集中可以简化维护 每个对象在自己状态改变时告诉中介者,每个对象对中介者发出的请求给予回应 中介者常常被用来协调GUI组建 中介者需要包含所有被中介对象的引用,被中介对象可以选择是否包含中介者引用(可以在方法调用时传入) 缺点: 中介者自身可能过于复杂

命令模式——HeadFirst设计模式学习笔记

命令模式:将"请求"封装成对象,以便使用不同的请求.日志.队列等来参数化其他对象.命令模式也支持撤销操作. 设计原则: 把方法的调用封装起来,调用此对象不需要知道它内部具体是如何运行的,只需要知道包装成型的方法 命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开 将"动作请求者"从"动作执行者"中解耦,即将发出请求的对象和接受并执行请求的对象分离开来.两者通过命令对象沟通 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象

蝇量模式——HeadFirst设计模式学习笔记

蝇量模式:让某个类的一个实例能够用来提供多个"虚拟"实例,运用共享技术有效地支持大量细粒度的对象 特点: 减少运行时对象实例的个数 将许多"虚拟"对象的状态一同管理 运用共享技术有效地支持大量细粒度的对象 区分对象的共享变量(内部状态)和不可共享变量(外部状态,将此类变量从类从剔除,由外部传入) 用途: 当一个类需要创建很多个实例,而这些实例可以被同一个方法控制 缺点: 单个逻辑实例将无法拥有独立不同的行为 举例: 你需要建立很多树对象,每个树对象有三个属性:位置坐

备忘录模式——HeadFirst设计模式学习笔记

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.可以将该对象恢复到原先保存的状态 Java中可以使用序列化机制保存状态 发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据. 备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态. 管理角色:对备忘录进行管理,保存和提供备忘录. 特点: 被存储的状态放在外面,不和关键对象放在一起 保持了关键对象的封装,提供实现恢复的能力 缺点: 资源与时间的消耗 举

代理模式——HeadFirst设计模式学习笔记

代理模式:为另一个对象提供一个替身或占位符控制这个对象的访问 特点: 让代理对象控制对象的访问,被代理对象可以是远程对象(远程代理),创建开销较大对象(虚拟代理),或需要安全控制的对象(保护代理) 代理分类: 远程代理:好比远程对象(在不同JVM虚拟机的对象)的本地代表(本地方法的行为转移到远程),帮助我们处理网络上的细节 代理假装自己是远程对象,不过只是一个中间角色,处理访问远程对象 Java RMI提供了客户辅助对象stub和服务辅助对象skeleton,并为其提供相同的方法 注意方法返回值

原型模式——HeadFirst设计模式学习笔记

原型模式:通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的(clone) 特点: 向用户隐藏了创建新实例的复杂性 让用户可以产生未知类型的对象,即只需知道对象实现了哪些接口,而无需知道具体是哪种实现 在某些情况下,复制对象比创建对象更高效 Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone

装饰者模式——HeadFirst 设计模式学习笔记

装饰者模式:动态的将责任附加到对象上,若要扩展功能,装饰者提供了更有弹性的替代方案. 设计原则: 类的设计应该对拓展开放,对修改关闭.允许类容易拓展,在不修改现有代码的情况下添加新的行为 特点: 装饰者和被装饰对象有相同的超类型,我们利用继承达到"类型匹配",而不是利用继承获得"行为". 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案.如果依赖继承,那么类的行为只能在编译时静态决定,行为不是来自超类就是子类覆盖后的版本,每当需

策略模式——HeadFirst 设计模式学习笔记

策略模式:策略模式定义了算法族,分别封装起来,让他们可以相互替换,此模式让算法的变化独立于使用算法的客户. 设计原则: 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起.以便以后轻松的更改或扩充此部分,而不影响不需要变化的其他部分 针对接口编程而不是针对实现编程.实际的实现不会被绑定,调用时只知道调用的接口,而无需知道具体的实现方式 多用组合,少用继承.使用组合有很大的弹性,可以在运行时动态改变行为 要点: 良好的OO设计必须遵循可复用,可拓展,可维护 大部分模式允

解释器模式——HeadFirst设计模式学习笔记

解释器模式:给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子 特点: 每一种语法设置为一个类,便于实现 便于扩展语言的语法 用与处理重复发生的交叉问题或解析一种语言 缺点: 解释器模式会引起类膨胀 效率不高 解释器模式采用递归调用方法 举例: 1 //解释器接口 2 public interface Expression { 3 public boolean interpret(String context); 4 } 5 6 //实现Or解释器 7 p