状态模式
状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
在下面的两种情况下均可使用State模式:
1) 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2) 代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
1) 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2) 代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
状态模式组成
环境类(Context): 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
抽象状态类(State): 定义一个接口以封装与Context的一个特定状态相关的行为。
具体状态类(ConcreteState): 每一子类实现一个与Context的一个状态相关的行为。
抽象状态类(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 }
客户端代码

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 }
运行结果
模式总结
优点
状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
所有状态相关的代码都存在于某个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 }
账户状态抽象对象: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 }
状态一: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 }
状态二: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 }
状态三: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 }
客户端代码:

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 }
运行结果:
应用举例二:后面再补充(SyOrderState)