状态模式

状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
 
在下面的两种情况下均可使用State模式:
1) 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2)  代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
 
状态模式组成
环境类(Context):  定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
抽象状态类(State):  定义一个接口以封装与Context的一个特定状态相关的行为。
具体状态类(ConcreteState):  每一子类实现一个与Context的一个状态相关的行为。
 
状态模式结构
 
状态模式实现代码
 1 /// <summary>
 2     /// Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
 3     /// </summary>
 4     public class Context
 5     {
 6         private State state;
 7         /// <summary>
 8         /// 定义Context的初始状态
 9         /// </summary>
10         /// <param name="state"></param>
11         public Context(State state)
12         {
13             this.state = state;
14         }
15 
16         /// <summary>
17         /// 可读写的状态属性,用于读取和设置新状态
18         /// </summary>
19         public State State
20         {
21             get { return state; }
22             set { state = value; }
23         }
24 
25         /// <summary>
26         /// 对请求做处理,并设置下一个状态
27         /// </summary>
28         public void Request()
29         {
30             state.Handle(this);
31         }
32     }
33 
34     /// <summary>
35     /// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
36     /// </summary>
37     public abstract class State
38     {
39         public abstract void Handle(Context context);
40     }
41 
42     /// <summary>
43     /// 具体状态类,每一个子类实现一个与Context的一个状态相关的行为
44     /// </summary>
45     public class ConcreteStateA : State
46     {
47         /// <summary>
48         /// 设置ConcreteStateA的下一个状态是ConcreteStateB
49         /// </summary>
50         /// <param name="context"></param>
51         public override void Handle(Context context)
52         {
53             Console.WriteLine("当前状态是 A.");
54             context.State = new ConcreteStateB();
55         }
56     }
57 
58     public class ConcreteStateB : State
59     {
60         /// <summary>
61         /// 设置ConcreteStateB的下一个状态是ConcreteSateA
62         /// </summary>
63         /// <param name="context"></param>
64         public override void Handle(Context context)
65         {
66             Console.WriteLine("当前状态是 B.");
67             context.State = new ConcreteStateA();
68         }
69     }
View Code

客户端代码

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             // 设置Context的初始状态为ConcreteStateA
 6             Context context = new Context(new ConcreteStateA());
 7 
 8             // 不断地进行请求,同时更改状态
 9             context.Request();
10             context.Request();
11             context.Request();
12             context.Request();
13 
14             Console.Read();
15         }
16     }
View Code

运行结果

模式总结

   优点

     状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。

     所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换。

     状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。

   缺点

     导致较多的ConcreteState子类,如果状态太多,就会创建太多的ConcreateState子类

  适用场景

     当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式来。

     一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态。

 

应用举例:

 假设现在有个银行账户,有三种类型AccountRedState,AccountRedState,AccountGoldState,在账户余额发生变化的时候会改变账户的状态,实现如下

账户上下文:AccountContext

 1 public class AccountContext
 2     {
 3         public AccountState AccountState { get; set; }
 4         public double AccountBalance { get { return AccountState.AccountBalance; } }
 5         public string Owner { get; set; }
 6         public AccountContext(string owner)
 7         {
 8             this.Owner = owner;
 9             this.AccountState = new AccountSilverState(0.00, this);
10         }
11 
12         /// <summary>
13         /// 存钱
14         /// </summary>
15         /// <param name="amount"></param>
16         public void Deposit(double amount)
17         {
18             AccountState.Deposit(amount);
19             Console.WriteLine("存款金额为 {0:C}——", amount);
20             Console.WriteLine("账户余额为 =:{0:C}", this.AccountBalance);
21             Console.WriteLine("账户状态为: {0}", this.AccountState.GetType().Name);
22             Console.WriteLine();
23         }
24 
25 
26         /// <summary>
27         /// 取钱
28         /// </summary>
29         /// <param name="amount"></param>
30         public void Withdraw(double amount)
31         {
32             AccountState.Withdraw(amount);
33             Console.WriteLine("取款金额为 {0:C}——", amount);
34             Console.WriteLine("账户余额为 =:{0:C}", this.AccountBalance);
35             Console.WriteLine("账户状态为: {0}", this.AccountState.GetType().Name);
36             Console.WriteLine();
37         }
38 
39 
40         /// <summary>
41         /// 获得利息
42         /// </summary>
43         public void PayInterest()
44         {
45             AccountState.PayInterest();
46             Console.WriteLine("Interest Paid --- ");
47             Console.WriteLine("账户余额为 =:{0:C}", this.AccountBalance);
48             Console.WriteLine("账户状态为: {0}", this.AccountState.GetType().Name);
49             Console.WriteLine();
50         }
51     }
View Code

账户状态抽象对象:AccountState

 1 public abstract class AccountState
 2     {
 3         public AccountContext AccountContext { get; set; }
 4         /// <summary>
 5         /// 余额
 6         /// </summary>
 7         public double AccountBalance { get; set; }
 8         /// <summary>
 9         /// 利率
10         /// </summary>
11         public double AccountInterest { get; set; }
12         /// <summary>
13         /// 下限
14         /// </summary>
15         public double AccountLowerLimit { get; set; }
16         /// <summary>
17         /// 上限
18         /// </summary>
19         public double AccountUpperLimit { get; set; }
20         /// <summary>
21         /// 存款
22         /// </summary>
23         /// <param name="amount"></param>
24         public abstract void Deposit(double amount);
25         /// <summary>
26         /// 取钱
27         /// </summary>
28         /// <param name="amount"></param>
29         public abstract void Withdraw(double amount);
30         /// <summary>
31         /// 获得的利息
32         /// </summary>
33         public abstract void PayInterest();
34     }
View Code

状态一:AccountRedState

 1  public class AccountRedState : AccountState
 2     {
 3         public AccountRedState(AccountState state)
 4         {
 5 
 6             // Initialize
 7             this.AccountBalance = state.AccountBalance;
 8             this.AccountContext = state.AccountContext;
 9             AccountInterest = 0.00;
10             AccountLowerLimit = -100.00;
11             AccountUpperLimit = 0.00;
12         }
13         // 存款
14         public override void Deposit(double amount)
15         {
16             AccountBalance += amount;
17             StateChangeCheck();
18         }
19 
20         // 取钱
21         public override void Withdraw(double amount)
22         {
23             Console.WriteLine("没有钱可以取了!");
24         }
25 
26         public override void PayInterest()
27         {
28 
29             // 没有利息
30         }
31 
32         private void StateChangeCheck()
33         {
34             if (AccountBalance > AccountUpperLimit)
35             {
36                 AccountContext.AccountState = new AccountSilverState(this);
37             }
38         }
39     }
View Code

状态二:AccountSilverState

 1  public class AccountSilverState : AccountState
 2     {
 3         public AccountSilverState(AccountState state)
 4             : this(state.AccountBalance, state.AccountContext)
 5         {
 6         }
 7 
 8         public AccountSilverState(double balance, AccountContext account)
 9         {
10             this.AccountBalance = balance;
11             this.AccountContext = account;
12             AccountInterest = 0.00;
13             AccountLowerLimit = 0.00;
14             AccountUpperLimit = 1000.00;
15         }
16 
17         public override void Deposit(double amount)
18         {
19             AccountBalance += amount;
20             StateChangeCheck();
21         }
22         public override void Withdraw(double amount)
23         {
24             AccountBalance -= amount;
25             StateChangeCheck();
26         }
27 
28         public override void PayInterest()
29         {
30             AccountBalance += AccountInterest * AccountBalance;
31             StateChangeCheck();
32         }
33 
34         private void StateChangeCheck()
35         {
36             if (AccountBalance < AccountLowerLimit)
37             {
38                 AccountContext.AccountState = new AccountRedState(this);
39             }
40             else if (AccountBalance > AccountUpperLimit)
41             {
42                 AccountContext.AccountState = new AccountGoldState(this);
43             }
44         }
45     }
View Code

状态三:AccountGoldState

 1  public class AccountGoldState : AccountState
 2     {
 3         public AccountGoldState(AccountState state)
 4         {
 5             this.AccountBalance = state.AccountBalance;
 6             this.AccountContext = state.AccountContext;
 7             AccountInterest = 0.05;
 8             AccountLowerLimit = 1000.00;
 9             AccountUpperLimit = 1000000.00;
10         }
11 
12         // 存钱
13         public override void Deposit(double amount)
14         {
15             AccountBalance += amount;
16             StateChangeCheck();
17         }
18 
19         // 取钱
20         public override void Withdraw(double amount)
21         {
22             AccountBalance -= amount;
23             StateChangeCheck();
24         }
25         public override void PayInterest()
26         {
27             AccountBalance += AccountInterest * AccountBalance;
28             StateChangeCheck();
29         }
30 
31         private void StateChangeCheck()
32         {
33             if (AccountBalance < 0.0)
34             {
35                 AccountContext.AccountState = new AccountRedState(this);
36             }
37             else if (AccountBalance < AccountLowerLimit)
38             {
39                 AccountContext.AccountState = new AccountSilverState(this);
40             }
41         }
42     }
View Code

客户端代码:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             AccountContext context = new AccountContext("rainTest");
 6             // 进行交易
 7             // 存钱
 8             context.Deposit(1000.0);
 9             context.Deposit(200.0);
10             context.Deposit(600.0);
11             // 付利息
12             context.PayInterest();
13             // 取钱
14             context.Withdraw(2000.00);
15             context.Withdraw(500.00);
16             // 等待用户输入
17             Console.ReadKey();
18         }
19     }
View Code

运行结果:

 

应用举例二:后面再补充(SyOrderState)

posted @ 2015-11-27 21:18  AntColony  阅读(132)  评论(0)    收藏  举报