行为型模式之状态模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了行为型模式之状态模式相关的知识,希望对你有一定的参考价值。
概述
状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。
定义
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
实现
银行账户类
//银行账户:环境类 public class Account { public AccountState State { get; set; } //维持一个对抽象状态对象的引用 public String Owner { get; set; } //开户名 public double Balance { get; set; } //账户余额 public Account(String owner, double init) { this.Owner = owner; this.Balance = init; this.State = new NormalState(this); //设置初始状态 Console.WriteLine(this.Owner + "开户,初始金额为" + init); Console.WriteLine("---------------------------------------------"); } /// <summary> /// 存款方法 /// </summary> /// <param name="amount"></param> public void Deposit(double amount) { Console.WriteLine(this.Owner + "存款" + amount); State.Deposit(amount); Console.WriteLine("现在余额为" + this.Balance); Console.WriteLine("现在帐户状态为" + State.GetType().Name); Console.WriteLine("---------------------------------------------"); } public void Withdraw(double amount) { Console.WriteLine(this.Owner + "取款" + amount); State.Withdraw(amount); //调用状态对象的withdraw()方法 Console.WriteLine("现在余额为" + this.Balance); Console.WriteLine("现在帐户状态为" + this.State.GetType().Name); Console.WriteLine("---------------------------------------------"); } public void ComputeInterest() { State.ComputeInterest(); //调用状态对象的computeInterest()方法 } }
状态类
/// <summary> /// 抽象状态类 /// </summary> public abstract class AccountState { public Account account { get; set; } /// <summary> /// 存款方法 /// </summary> /// <param name="amount"></param> public abstract void Deposit(double amount); /// <summary> /// 取款方法 /// </summary> /// <param name="amount"></param> public abstract void Withdraw(double amount); /// <summary> /// 计算利息 /// </summary> public abstract void ComputeInterest(); /// <summary> /// 状态转换 /// </summary> public abstract void StateCheck(); }
//正常状态:具体状态类 public class NormalState : AccountState { public NormalState(Account account) { this.account = account; } public NormalState(AccountState state) { this.account = state.account; } public override void Deposit(double amount) { account.Balance += amount; StateCheck(); } public override void Withdraw(double amount) { account.Balance -= amount; StateCheck(); } public override void ComputeInterest() { Console.WriteLine("正常状态,无须支付利息!"); } /// <summary> /// 状态转换 /// </summary> public override void StateCheck() { if (account.Balance > -2000 && account.Balance <= 0) { account.State = new OverdraftState(this); } else if (account.Balance == -2000) { account.State = new RestrictedState(this); } else if (account.Balance < -2000) { Console.WriteLine("操作受限!"); } } }
/// <summary> /// 透支状态:具体状态类 /// </summary> public class OverdraftState : AccountState { public OverdraftState(AccountState state) { this.account = state.account; } public override void Deposit(double amount) { account.Balance += amount; StateCheck(); } public override void Withdraw(double amount) { account.Balance -= amount; StateCheck(); } public override void ComputeInterest() { Console.WriteLine("计算利息!"); } /// <summary> /// 状态转换 /// </summary> public override void StateCheck() { if (account.Balance > 0) { account.State = new NormalState(this); } else if (account.Balance == -2000) { account.State = new RestrictedState(this); } else if (account.Balance < -2000) { Console.WriteLine("操作受限!"); } } }
/// <summary> /// 受限状态:具体状态类 /// </summary> public class RestrictedState : AccountState { public RestrictedState(AccountState state) { this.account = state.account; } public override void Deposit(double amount) { account.Balance += amount; StateCheck(); } public override void Withdraw(double amount) { Console.WriteLine("帐号受限,取款失败"); } public override void ComputeInterest() { Console.WriteLine("计算利息!"); } public override void StateCheck() { if (account.Balance > 0) { account.State = new NormalState(this); } else if (account.Balance > -2000) { account.State = new OverdraftState(this); } } }
客户端
class Program { static void Main(string[] args) { Account acc = new Account("段誉", 0.0); acc.Deposit(1000); acc.Withdraw(2000); acc.Deposit(3000); acc.Withdraw(4000); acc.Withdraw(1000); acc.ComputeInterest(); Console.ReadLine(); } }
结果
总结
状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端的使用。在实际开发中,状态模式具有较高的使用频率,在工作流和游戏开发中状态模式都得到了广泛的应用,例如公文状态的转换、游戏中角色的升级等。
主要优点
1、封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
2、 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
3、允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
4、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
主要缺点
1、 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
2、 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
3、 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
以上是关于行为型模式之状态模式的主要内容,如果未能解决你的问题,请参考以下文章