19.设计模式_状态者模式

一、引言

  在上一篇文章介绍到可以使用状态者模式和观察者模式来解决中介者模式存在的问题,在本文中将首先通过一个银行账户的例子来解释状态者模式,通过这个例子使大家可以对状态者模式有一个清楚的认识,接着,再使用状态者模式来解决上一篇文章中提出的问题。

二、状态者模式的介绍

  每个对象都有其对应的状态,而每个状态又对应一些相应的行为,如果某个对象有多个状态时,那么就会对应很多的行为。那么对这些状态的判断和根据状态完成的行为,就会导致多重条件语句,并且如果添加一种新的状态时,需要更改之前现有的代码。这样的设计显然违背了开闭原则。状态模式正是用来解决这样的问题的。状态模式将每种状态对应的行为抽象出来成为单独新的对象,这样状态的变化不再依赖于对象内部的行为。

2.1 状态者模式的定义

  上面对状态模式做了一个简单的介绍,这里给出状态模式的定义。

  状态模式——允许一个对象在其内部状态改变时自动改变其行为,对象看起来就像是改变了它的类。

2.2 状态者模式的结构

  既然状态者模式是对已有对象的状态进行抽象,则自然就有抽象状态者类和具体状态者类,而原来已有对象需要保存抽象状态者类的引用,通过调用抽象状态者的行为来改变已有对象的行为。经过上面的分析,状态者模式的结构图也就很容易理解了,具体结构图如下图示。

  

  从上图可知,状态者模式涉及以下三个角色:

  • Account类:维护一个State类的一个实例,该实例标识着当前对象的状态。
  • State类:抽象状态类,定义了一个具体状态类需要实现的行为约定。
  • SilveStater、GoldState和RedState类:具体状态类,实现抽象状态类的每个行为。

2.3 状态者模式的实现

  下面,就以银行账户的状态来实现下状态者模式。银行账户根据余额可分为RedState、SilverState和GoldState。这些状态分别代表透支账号,新开账户和标准账户。账号余额在【-100.0,0.0】范围表示处于RedState状态,账号余额在【0.0 , 1000.0】范围表示处于SilverState,账号在【1000.0, 100000.0】范围表示处于GoldState状态。下面以这样的一个场景实现下状态者模式,具体实现代码如下所示:

  1 namespace StatePatternSample
  2 {
  3     public class Account
  4     {
  5         public State State {get;set;}
  6         public string Owner { get; set; }
  7         public Account(string owner)
  8         {
  9             this.Owner = owner;
 10             this.State = new SilverState(0.0, this);
 11         }
 12
 13         public double Balance { get {return State.Balance; }} // 余额
 14         // 存钱
 15         public void Deposit(double amount)
 16         {
 17             State.Deposit(amount);
 18             Console.WriteLine("存款金额为 {0:C}——", amount);
 19             Console.WriteLine("账户余额为 =:{0:C}", this.Balance);
 20             Console.WriteLine("账户状态为: {0}", this.State.GetType().Name);
 21             Console.WriteLine();
 22         }
 23
 24         // 取钱
 25         public void Withdraw(double amount)
 26         {
 27             State.Withdraw(amount);
 28              Console.WriteLine("取款金额为 {0:C}——",amount);
 29             Console.WriteLine("账户余额为 =:{0:C}", this.Balance);
 30             Console.WriteLine("账户状态为: {0}", this.State.GetType().Name);
 31             Console.WriteLine();
 32         }
 33
 34         // 获得利息
 35         public void PayInterest()
 36         {
 37             State.PayInterest();
 38             Console.WriteLine("Interest Paid --- ");
 39             Console.WriteLine("账户余额为 =:{0:C}", this.Balance);
 40             Console.WriteLine("账户状态为: {0}", this.State.GetType().Name);
 41             Console.WriteLine();
 42         }
 43     }
 44
 45     // 抽象状态类
 46     public abstract class State
 47     {
 48         // Properties
 49         public Account Account { get; set; }
 50         public double Balance { get; set; } // 余额
 51         public double Interest { get; set; } // 利率
 52         public double LowerLimit { get; set; } // 下限
 53         public double UpperLimit { get; set; } // 上限
 54
 55         public abstract void Deposit(double amount); // 存款
 56         public abstract void Withdraw(double amount); // 取钱
 57         public abstract void PayInterest(); // 获得的利息
 58     }
 59
 60     // Red State意味着Account透支了
 61     public class RedState : State
 62     {
 63         public RedState(State state)
 64         {
 65             // Initialize
 66             this.Balance = state.Balance;
 67             this.Account = state.Account;
 68             Interest = 0.00;
 69             LowerLimit = -100.00;
 70             UpperLimit = 0.00;
 71         }
 72
 73         // 存款
 74         public override void Deposit(double amount)
 75         {
 76             Balance += amount;
 77             StateChangeCheck();
 78         }
 79         // 取钱
 80         public override void Withdraw(double amount)
 81         {
 82             Console.WriteLine("没有钱可以取了!");
 83         }
 84
 85         public override void PayInterest()
 86         {
 87             // 没有利息
 88         }
 89
 90         private void StateChangeCheck()
 91         {
 92             if (Balance > UpperLimit)
 93             {
 94                 Account.State = new SilverState(this);
 95             }
 96         }
 97     }
 98
 99     // Silver State意味着没有利息得
100     public class SilverState :State
101     {
102         public SilverState(State state)
103             : this(state.Balance, state.Account)
104         {
105         }
106
107         public SilverState(double balance, Account account)
108         {
109             this.Balance = balance;
110             this.Account = account;
111             Interest = 0.00;
112             LowerLimit = 0.00;
113             UpperLimit = 1000.00;
114         }
115
116         public override void Deposit(double amount)
117         {
118             Balance += amount;
119             StateChangeCheck();
120         }
121         public override void Withdraw(double amount)
122         {
123             Balance -= amount;
124             StateChangeCheck();
125         }
126
127         public override void PayInterest()
128         {
129             Balance += Interest * Balance;
130             StateChangeCheck();
131         }
132
133         private void StateChangeCheck()
134         {
135             if (Balance < LowerLimit)
136             {
137                 Account.State = new RedState(this);
138             }
139             else if (Balance > UpperLimit)
140             {
141                 Account.State = new GoldState(this);
142             }
143         }
144     }
145
146     // Gold State意味着有利息状态
147     public class GoldState : State
148     {
149         public GoldState(State state)
150         {
151             this.Balance = state.Balance;
152             this.Account = state.Account;
153             Interest = 0.05;
154             LowerLimit = 1000.00;
155             UpperLimit = 1000000.00;
156         }
157         // 存钱
158         public override void Deposit(double amount)
159         {
160             Balance += amount;
161             StateChangeCheck();
162         }
163         // 取钱
164         public override void Withdraw(double amount)
165         {
166             Balance -= amount;
167             StateChangeCheck();
168         }
169         public override void PayInterest()
170         {
171             Balance += Interest * Balance;
172             StateChangeCheck();
173         }
174
175         private void StateChangeCheck()
176         {
177             if (Balance < 0.0)
178             {
179                 Account.State = new RedState(this);
180             }
181             else if (Balance < LowerLimit)
182             {
183                 Account.State = new SilverState(this);
184             }
185         }
186     }
187
188     class App
189     {
190         static void Main(string[] args)
191         {
192             // 开一个新的账户
193             Account account = new Account("Learning Hard");
194
195             // 进行交易
196             // 存钱
197             account.Deposit(1000.0);
198             account.Deposit(200.0);
199             account.Deposit(600.0);
200
201             // 付利息
202             account.PayInterest();
203
204             // 取钱
205             account.Withdraw(2000.00);
206             account.Withdraw(500.00);
207
208             // 等待用户输入
209             Console.ReadKey();
210         }
211     }
212 }

  上面代码的运行结果如下图所示:

  从上图可以发现,进行存取款交易,会影响到Account内部的状态,由于状态的改变,从而影响到Account类行为的改变,而且这些操作都是发生在运行时的。

三、应用状态者模式完善中介者模式方案

  在上一篇博文中,我曾介绍到中介者模式存在的问题,详细的问题描述可以参考上一篇博文。下面利用观察者模式和状态者模式来完善中介者模式,具体的实现代码如下所示:

  1  // 抽象牌友类
  2     public abstract class AbstractCardPartner
  3     {
  4         public int MoneyCount { get; set; }
  5
  6         public AbstractCardPartner()
  7         {
  8             MoneyCount = 0;
  9         }
 10
 11         public abstract void ChangeCount(int Count, AbstractMediator mediator);
 12     }
 13
 14     // 牌友A类
 15     public class ParterA : AbstractCardPartner
 16     {
 17         // 依赖与抽象中介者对象
 18         public override void ChangeCount(int Count, AbstractMediator mediator)
 19         {
 20             mediator.ChangeCount(Count);
 21         }
 22     }
 23
 24     // 牌友B类
 25     public class ParterB : AbstractCardPartner
 26     {
 27         // 依赖与抽象中介者对象
 28         public override void ChangeCount(int Count, AbstractMediator mediator)
 29         {
 30             mediator.ChangeCount(Count);
 31         }
 32     }
 33
 34     // 抽象状态类
 35     public abstract class State
 36     {
 37         protected AbstractMediator meditor;
 38         public abstract void ChangeCount(int count);
 39     }
 40
 41     // A赢状态类
 42     public class AWinState : State
 43     {
 44         public AWinState(AbstractMediator concretemediator)
 45         {
 46             this.meditor = concretemediator;
 47         }
 48
 49         public override void ChangeCount(int count)
 50         {
 51             foreach (AbstractCardPartner p in meditor.list)
 52             {
 53                 ParterA a = p as ParterA;
 54                 //
 55                 if (a != null)
 56                 {
 57                     a.MoneyCount += count;
 58                 }
 59                 else
 60                 {
 61                     p.MoneyCount -= count;
 62                 }
 63             }
 64         }
 65     }
 66
 67     // B赢状态类
 68     public class BWinState : State
 69     {
 70         public BWinState(AbstractMediator concretemediator)
 71         {
 72             this.meditor = concretemediator;
 73         }
 74
 75         public override void ChangeCount(int count)
 76         {
 77             foreach (AbstractCardPartner p in meditor.list)
 78             {
 79                 ParterB b = p as ParterB;
 80                 // 如果集合对象中时B对象,则对B的钱添加
 81                 if (b != null)
 82                 {
 83                     b.MoneyCount += count;
 84                 }
 85                 else
 86                 {
 87                     p.MoneyCount -= count;
 88                 }
 89             }
 90         }
 91     }
 92
 93     // 初始化状态类
 94     public class InitState : State
 95     {
 96         public InitState()
 97         {
 98             Console.WriteLine("游戏才刚刚开始,暂时还有玩家胜出");
 99         }
100
101         public override void ChangeCount(int count)
102         {
103             //
104             return;
105         }
106     }
107
108     // 抽象中介者类
109     public abstract class AbstractMediator
110     {
111         public List<AbstractCardPartner> list = new List<AbstractCardPartner>();
112
113         public State State { get; set; }
114
115         public AbstractMediator(State state)
116         {
117             this.State = state;
118         }
119
120         public void Enter(AbstractCardPartner partner)
121         {
122             list.Add(partner);
123         }
124
125         public void Exit(AbstractCardPartner partner)
126         {
127             list.Remove(partner);
128         }
129
130         public void ChangeCount(int count)
131         {
132             State.ChangeCount(count);
133         }
134     }
135
136     // 具体中介者类
137     public class MediatorPater : AbstractMediator
138     {
139         public MediatorPater(State initState)
140             : base(initState)
141         { }
142     }
143
144     class Program
145     {
146         static void Main(string[] args)
147         {
148             AbstractCardPartner A = new ParterA();
149             AbstractCardPartner B = new ParterB();
150             // 初始钱
151             A.MoneyCount = 20;
152             B.MoneyCount = 20;
153
154             AbstractMediator mediator = new MediatorPater(new InitState());
155
156             // A,B玩家进入平台进行游戏
157             mediator.Enter(A);
158             mediator.Enter(B);
159
160             // A赢了
161             mediator.State = new AWinState(mediator);
162             mediator.ChangeCount(5);
163             Console.WriteLine("A 现在的钱是:{0}", A.MoneyCount);// 应该是25
164             Console.WriteLine("B 现在的钱是:{0}", B.MoneyCount); // 应该是15
165
166             // B 赢了
167             mediator.State = new BWinState(mediator);
168             mediator.ChangeCount(10);
169             Console.WriteLine("A 现在的钱是:{0}", A.MoneyCount);// 应该是25
170             Console.WriteLine("B 现在的钱是:{0}", B.MoneyCount); // 应该是15
171             Console.Read();
172         }
173     }

四、状态者模式的应用场景

  在以下情况下可以考虑使用状态者模式。

  • 当一个对象状态转换的条件表达式过于复杂时可以使用状态者模式。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
  • 当一个对象行为取决于它的状态,并且它需要在运行时刻根据状态改变它的行为时,就可以考虑使用状态者模式。

五、状态者模式的优缺点

  状态者模式的主要优点是:

  • 将状态判断逻辑每个状态类里面,可以简化判断的逻辑。
  • 当有新的状态出现时,可以通过添加新的状态类来进行扩展,扩展性好。

  状态者模式的主要缺点是:

  • 如果状态过多的话,会导致有非常多的状态类,加大了开销。

六、总结

  状态者模式是对对象状态的抽象,从而把对象中对状态复杂的判断逻辑已到各个状态类里面,从而简化逻辑判断。在下一篇文章将分享我对策略模式的理解。

时间: 2024-10-11 06:08:09

19.设计模式_状态者模式的相关文章

大话设计模式_备忘录模式(Java代码)

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 简单描述:一个Memento类,代表Originator中要备份的属性.Originator负责生成备份和还原备份,CareTaker负责存储备份 大话设计模式中的截图: 例子代码: Memento类: 1 package com.longsheng.memento; 2 3 public class Memento { 4 5 private String sta

大话设计模式_解释器模式(Java代码)

解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 简单描述:一个AbstractExpression类,多个子类,存在一个Interpret方法,转义Context对象的信息.客户端根据信息实例化不同的Expression类,并调用其转义方法(这个过程可以使用简单工厂+反射进行) 大话设计模式中的截图: 代码例子: 假设HTML代码解释器: (1)第一类标签<HTML>(开始)/<HEAD>(头信息)/<BODY&g

大话设计模式_原型模式(Java代码)

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 简单描述:即通过实现接口Cloneable重写方法clone(),使得创建新的拷贝对象不需要一个成员一个成员的重新复制,而且可以提高创建对象的效率 Java中要想实现拷贝使用clone()方法,类必须实现Cloneable接口,并且重写Object类中的clone()方法,调用父类的clone()方法即可实现浅复制 代码如下: WorkExperience类: 1 package com.longsheng.prototy

大话设计模式_状态模式(Java代码)

状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 简单描述:一个Context类(存有一个抽象状态State引用),调用状态类的方法.State的具体类方法中会判断Context类的状态(如时间),满足一个状态则执行相应动作,否则把Context的State引用指向下一个状态类,由下一个状态类决定相应行为 大话设计模式中的截图: 例子代码: Work类(Context): 1 package com.longsheng.state; 2 3 public cla

大话设计模式_建造者模式(Java代码)

建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 简单描述:1个产品类(可有可无,关键是建造流程),1个抽象建造步骤类,多个具体建造子类(不同的类建造不同的产品),1个指挥者(用于规定建造流程),客户端指定需要建造的具体类型,由指挥者建造好之后,建造者子类返回对应产品给客户 大话设计模式中的截图: 例子代码: Product类: 1 package com.longsheng.builder; 2 3 public class Product { 4 5 pr

大话设计模式_策略模式(Java代码)

策略模式:定义算法家族,分别封装,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户 简单描述:一个父类,多个子类实现具体方法.一个Context类持有父类的引用(使用子类实例化此引用),客户端代码只需要与此Context类交互即可 大话设计模式中的截图: 例子代码: 策略类: 1 package com.longsheng.strategy; 2 3 public abstract class Strategy { 4 5 public abstract double getR

大话设计模式_模板方法模式(Java代码)

模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 简单描述:多个类的行为是差不多的,只是某些局部不一样,则交由父类中抽象出这些子类中相同的部分,父类中定义出不同的部分的接口(方法),这些不同部分的方法则由子类去实现,通过多态,实现代码的重用 大话设计模式中的截图: 例子代码: AbstractClass类: 1 package com.longsheng.templatemethod; 2 3 public

05.设计模式_建造者模式

转载自  http://www.cnblogs.com/zhili/p/BuilderPattern.html 一.引言 在软件系统中,有时需要创建一个复杂对象,并且这个复杂对象由其各部分子对象通过一定的步骤组合而成.例如一个采购系统中,如果需要采购员去采购一批电脑时,在这个实际需求中,电脑就是一个复杂的对象,它是由CPU.主板.硬盘.显卡.机箱等组装而成的,如果此时让采购员一台一台电脑去组装的话真是要累死采购员了,这里就可以采用建造者模式来解决这个问题,我们可以把电脑的各个组件的组装过程封装到

22.设计模式_访问者模式

一.引言 在上一篇博文中分享了责任链模式,责任链模式主要应用在系统中的某些功能需要多个对象参与才能完成的场景.在这篇博文中,我将为大家分享我对访问者模式的理解. 二.访问者模式介绍 2.1 访问者模式的定义 访问者模式是封装一些施加于某种数据结构之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保存不变.访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变. 数据结构的每一个节点都可以接受一个访问者的调用