当前位置:首页 > .Net > C#设计模式系列(19)-状态者模式

C#设计模式系列(19)-状态者模式

状态模式,顾名思义,允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
程序员

一、引言

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

二、状态者模式的介绍

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

2.1 状态者模式的定义

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

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

2.2 状态者模式的结构

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

Csharp

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

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

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

csharp_list19_2

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

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

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

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

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

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

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

五、状态者模式的优缺点

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

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

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

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

六、总结

状态者模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

  • << C#设计模式系列(18)-中介者模式
  • C#设计模式系列(20)-策略者模式 >>
  • 作者:
    除非注明,本文原创:知道91,欢迎转载!转载请以链接形式注明本文地址,谢谢。
    原文链接:http://www.zhidao91.com/csharp-list19/

    相关文章 近期热评 最新文章

    • 使用微信JDK实现微信接口签名验证
      要使用微信的接口必须在绑定的域名下测试;签名必须先向微信请求到access_token,然后用access_token再去请求jsapi_ticket,最后用jsapi_ticket和相关的参数按照ASCII码...
    • oracle数据库相关操作注意事项
      修改Oracle SGA(共享内存) 很多网站说修改Oracle的内存通过命令 如果你这么做了,那么恭喜你,你的Oracle数据库无法启动了。如果你已经这么做了,恢复Oracle启动的方...
    • oracle数据库相关操作注意事项
      修改Oracle SGA(共享内存) 很多网站说修改Oracle的内存通过命令 如果你这么做了,那么恭喜你,你的Oracle数据库无法启动了。如果你已经这么做了,恢复Oracle启动的方...
    • 使用微信JDK实现微信接口签名验证
      要使用微信的接口必须在绑定的域名下测试;签名必须先向微信请求到access_token,然后用access_token再去请求jsapi_ticket,最后用jsapi_ticket和相关的参数按照ASCII码...
    • ABP开发指南系列教程(2) – 多层架构...
      为了减少复杂性和提高代码的可重用性,采用分层架构是一种被广泛接受的技术。为了实现分层的体系结构,ABP遵循DDD(领域驱动设计)的原则,将工程分为四个层: 展现层(...
    • ABP开发指南系列教程(1) – 入...
      ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。 ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WE...
    • Windows下 JIRA + Agile + Mysql 破解...
      本文讲述了Windows下 JIRA + Agile + Mysql 破解安装示例教程
    • c#类的构造函数继承关系示例剖析
      本文通过示例代码讲解了c#子类的构造函数与父类的关系,子类怎样集成父类的构造函数的。