博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
行为型---状态者模式(State Pattern)
阅读量:5884 次
发布时间:2019-06-19

本文共 13833 字,大约阅读时间需要 46 分钟。

状态者模式的介绍

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

状态者模式的定义

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

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

状态者模式的结构

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

  • State----抽象状态角色
          接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。 
  • ConcreteState----具体状态角色
          本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。 
  • Context----环境角色
          定义客户端需要的接口,并且负责具体状态的切换。
 
    环境角色有两个不成文的约束:    
  • 把状态对象声明为静态常量,有几个状态对象就声明几个静态常量。
  • 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。
 
具体代码实现:
namespace ConsoleApplication1{    ///     /// 抽象状态角色    ///     public abstract class State    {        //定义一个环境角色,提供子类访问        protected Context context;        public Context Context        {            set { context = value; }        }        //行为1        public abstract void handle1();        //行为2        public abstract void handle2();    }    ///     /// 具体状态角色    ///     public class ConcreteState1 : State    {        public override void handle1()        {            //本状态下必须处理的逻辑        }        public override void handle2()        {            //设置当前状态为state2            context.CurrentState = Context.STATE2;            //过渡到state2状态,由Context实现            context.handle2();        }    }    ///     /// 具体状态角色    ///     public class ConcreteState2 : State    {        public override void handle1()        {            //设置当前状态为state1            context.CurrentState = Context.STATE1;            //过渡到state1状态,由Context实现            context.handle1();                }        public override void handle2()        {            //本状态下必须处理的逻辑        }    }    ///     /// 具体环境角色    ///     public class Context    {        //定义状态        public static State STATE1 = new ConcreteState1();        public static State STATE2 = new ConcreteState2();        //当前状态        private State currentState;        public State CurrentState        {            get            {                //获取当前状态                return currentState;            }            set            {                //设置当前状态                currentState=value;                currentState.Context=this;            }        }        //行为委托        public void handle1()        {            currentState.handle1();        }        public void handle2()        {            currentState.handle2();        }    }    class Program    {        static void Main(string[] args)        {            //定义环境角色            Context context = new Context();            //初始化状态            context.CurrentState = new ConcreteState1();            //行为执行            context.handle1();            context.handle2();            Console.ReadLine();        }    }}
View Code

状态者模式的优缺点

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

  • 结构清晰
          避免了过多的switch...case或者if...else语句使用,避免了程序的复杂性,提高系统的可维护性。 
  • 遵循设计原则
          很好的体现了开闭原则和单一职责原则,每个状态都是一个子类,你要增加状态就要增加子类,你要修改状态,你只修改一个子类就可以了。 
  • 封装性非常好
          状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。
 

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

  • 子类会太多,也就是类膨胀。 

状态者模式的应用场景

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

  • 行为随状态改变而改变的场景 
  • 条件、分组判断语句的替代者
          在程序中大量使用switch语句或者if判断语句会导致程序结构不清晰,逻辑混乱,使用状态模式可以很好地避免这一问题,它通过扩展子类 实现了条件的判断处理。

应用一:

用状态模式来模拟一个电梯的状态场景:

具体代码实现:

namespace ConsoleApplication1{    ///     /// 抽象电梯状态    ///     public abstract class LiftState    {        protected Context context;        public Context Context        {            set { context = value; }        }        //首先电梯们开启动作        public abstract void open();        //电梯们有开启,那当然也就有关闭了        public abstract void close();        //电梯要能上能下,运行起来        public abstract void run();        //电梯还要能停下来        public abstract void stop();    }    ///     /// 敞门状态    ///     public class OpenningState : LiftState    {        //打开电梯门        public override void open()        {            Console.WriteLine("电梯门开启...");        }        public override void close()        {            context.LiftState = Context.closeingState;            context.LiftState.close();        }        public override void run()        {                   }        public override void stop()        {                   }    }    ///     /// 关闭状态    ///     public class CloseingState : LiftState    {        //电梯门关了再打开        public override void open()        {            //设置为敞门状态            context.LiftState = Context.openningState;            context.LiftState.open();        }        //电梯门关闭,这是关闭状态要实现的动作        public override void close()        {            Console.WriteLine("电梯门关闭...");        }        //电梯门关了就运行        public override void run()        {            //设置为运行状态            context.LiftState = Context.runingState;            context.LiftState.run();        }        //电梯门关着        public override void stop()        {            //设置为停止状态            context.LiftState = Context.stoppingState;            context.LiftState.stop();        }    }    ///     /// 运行状态    ///     public class RunningSate : LiftState    {        public override void open()        {                   }        public override void close()        {                   }        public override void run()        {            Console.WriteLine("电梯上下运行...");        }        public override void stop()        {            //设置为停止状态            context.LiftState = Context.stoppingState;            context.LiftState.stop();        }    }    ///     /// 停止状态    ///     public class StoppingState : LiftState    {        public override void open()        {            //设置为敞门状态            context.LiftState = Context.openningState;            context.LiftState.open();        }        public override void close()        {                   }        public override void run()        {            //设置为运行状态            context.LiftState = Context.runingState;            context.LiftState.run();        }        public override void stop()        {            Console.WriteLine("电梯停止了...");        }    }    ///     /// 上下文类    ///     public class Context    {        //定义出所有的电梯状态        public static OpenningState openningState = new OpenningState();        public static CloseingState closeingState = new CloseingState();        public static RunningSate runingState = new RunningSate();        public static StoppingState stoppingState = new StoppingState();        //定义一个当前电梯状态        private LiftState liftState;        public LiftState LiftState        {            get            {                return liftState;            }            set            {                liftState = value;                //把当前的环境通知到各个实现类中                liftState.Context = this;            }        }        public void open()        {            liftState.open();        }        public void close()        {            liftState.close();        }        public void run()        {            liftState.run();        }        public void stop()        {            liftState.stop();        }    }    class Program    {        static void Main(string[] args)        {            Context context = new Context();            context.LiftState = new CloseingState();            context.open();            context.close();            context.run();            context.stop();            Console.ReadLine();        }    }}
View Code

 

应用二:

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

namespace ConsoleApplication1{    ///     /// 抽象存款状态    ///     public abstract class State    {        protected Account context;        public Account Context        {            set { context = value; }        }        ///         /// 余额        ///         /// 利率        ///         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(); // 获得的利息        public void Display(string OperationType, double amount)        {            switch (OperationType)            {                case "Deposit":                    Console.WriteLine("存款金额为 {0:C}——", amount);                    Console.WriteLine("账户余额为 =:{0:C}", this.Balance);                    Console.WriteLine("账户状态为: {0}", this.GetType().Name);                    Console.WriteLine();                    break;                case "Withdraw":                    Console.WriteLine("取款金额为 {0:C}——", amount);                    Console.WriteLine("账户余额为 =:{0:C}", this.Balance);                    Console.WriteLine("账户状态为: {0}", this.GetType().Name);                    Console.WriteLine();                    break;                case "PayInterest":                    Console.WriteLine("Interest Paid --- ");                    Console.WriteLine("账户余额为 =:{0:C}", this.Balance);                    Console.WriteLine("账户状态为: {0}", this.GetType().Name);                    Console.WriteLine();                    break;                default:                    break;            }        }    }    ///     /// Red State意味着Account透支    ///     public class RedState : State    {        public RedState()        {            Interest = 0.00;            LowerLimit = -100.00;            UpperLimit = 0.00;        }        public RedState(double balance)            :this()        {            this.Balance = balance;        }        // 存款        public override void Deposit(double amount)        {            Balance += amount;            if (Balance > UpperLimit)            {                context.AccountState = new SilverState(this.Balance); //Context.silverState;            }        }        // 取钱        public override void Withdraw(double amount)        {            Console.WriteLine("没有钱可以取了!");        }        public override void PayInterest()        {            // 没有利息        }    }    ///     /// Silver State意味着没有利息得    ///     public class SilverState : State    {        public SilverState()        {            Interest = 0.00;            LowerLimit = 0.00;            UpperLimit = 1000.00;        }        public SilverState(double balance)            :this()        {            this.Balance = balance;        }        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)            {                context.AccountState = new RedState(this.Balance);//Context.redState;            }            else if (Balance > UpperLimit)            {                context.AccountState = new GoldState(this.Balance);//Context.goldState;            }        }    }    ///     /// Gold State意味着有利息状态    ///     public class GoldState : State    {        public GoldState()        {            Interest = 0.05;            LowerLimit = 1000.00;            UpperLimit = 1000000.00;        }        public GoldState(double balance)            :this()        {            this.Balance = balance;        }        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)            {                context.AccountState = new RedState(this.Balance);//Context.redState;            }            else if (Balance < LowerLimit)            {                context.AccountState = new SilverState(this.Balance);//Context.silverState;            }        }    }    ///     /// 上下文类    ///     public class Account    {        //定义出所有的存款账户状态        //public static RedState redState = new RedState();        //public static SilverState silverState = new SilverState();        //public static GoldState goldState = new GoldState();        //定义一个当前存款账户状态        private State accountState;        public State AccountState        {            get            {                return accountState;            }            set            {                accountState = value;                //把当前的环境通知到各个实现类中                accountState.Context = this;            }        }        public void Deposit(double amount)        {            accountState.Deposit(amount);            accountState.Display("Deposit", amount);        }        public void Withdraw(double amount)        {            accountState.Withdraw(amount);            accountState.Display("Withdraw", amount);        }        public void PayInterest()        {            accountState.PayInterest();            accountState.Display("PayInterest", 0);        }    }    class Program    {        static void Main(string[] args)        {            Account account = new Account();            account.AccountState = new SilverState(0.0);            // 进行交易            // 存钱            account.Deposit(1000.0);            account.Deposit(200.0);            account.Deposit(600.0);            // 付利息            account.PayInterest();            // 取钱            account.Withdraw(2000.00);            account.Withdraw(500.00);            Console.ReadLine();        }    }}
View Code

 

转载于:https://www.cnblogs.com/scmail81/p/8688645.html

你可能感兴趣的文章
发展大数据不能抛弃“小数据”
查看>>
中了WannaCry病毒的电脑几乎都是Win 7
查看>>
学生机房虚拟化(九)系统操作设计思路
查看>>
nginx报错pread() returned only 0 bytes instead of 4091的分析
查看>>
HTML 字符实体
查看>>
质数因子
查看>>
Spring源码浅析之事务(四)
查看>>
[转载] Live Writer 配置写 CSDN、BlogBus、cnBlogs、163、sina 博客
查看>>
SQL:连表查询
查看>>
MySQL日期函数、时间函数总结(MySQL 5.X)
查看>>
c语言用尾插法新建链表和输出建好的链表
查看>>
Java基础学习总结(1)——equals方法
查看>>
高性能 Oracle JDBC 编程
查看>>
java 中ResultSet可以获取的数据类型及返回值类型列表
查看>>
ubuntu 13 安装SH程序
查看>>
支付宝升级延时到账功能
查看>>
ghost后只剩下一个盘的数据寻回方法
查看>>
输入输出练习
查看>>
Git commit message和工作流规范
查看>>
java面试。答案源于网上
查看>>