zoukankan      html  css  js  c++  java
  • 行为型---状态者模式(State Pattern)

    状态者模式的介绍

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

    状态者模式的定义

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

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

    状态者模式的结构

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

    • State----抽象状态角色
              接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。 
    • ConcreteState----具体状态角色
              本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。 
    • Context----环境角色
              定义客户端需要的接口,并且负责具体状态的切换。
     
        环境角色有两个不成文的约束:    
    • 把状态对象声明为静态常量,有几个状态对象就声明几个静态常量。
    • 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。
     
    具体代码实现:
    namespace ConsoleApplication1
    {
        /// <summary>
        /// 抽象状态角色
        /// </summary>
        public abstract class State
        {
            //定义一个环境角色,提供子类访问
            protected Context context;
            public Context Context
            {
                set { context = value; }
            }
            //行为1
            public abstract void handle1();
            //行为2
            public abstract void handle2();
        }
        /// <summary>
        /// 具体状态角色
        /// </summary>
        public class ConcreteState1 : State
        {
            public override void handle1()
            {
                //本状态下必须处理的逻辑
            }
            public override void handle2()
            {
                //设置当前状态为state2
                context.CurrentState = Context.STATE2;
                //过渡到state2状态,由Context实现
                context.handle2();
            }
        }
        /// <summary>
        /// 具体状态角色
        /// </summary>
        public class ConcreteState2 : State
        {
            public override void handle1()
            {
                //设置当前状态为state1
                context.CurrentState = Context.STATE1;
                //过渡到state1状态,由Context实现
                context.handle1();        
            }
            public override void handle2()
            {
                //本状态下必须处理的逻辑
            }
        }
        /// <summary>
        /// 具体环境角色
        /// </summary>
        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
    {
        /// <summary>
        /// 抽象电梯状态
        /// </summary>
        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();
        }
    
        /// <summary>
        /// 敞门状态
        /// </summary>
        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()
            {
               
            }
        }
    
        /// <summary>
        /// 关闭状态
        /// </summary>
        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();
            }
        }
    
        /// <summary>
        /// 运行状态
        /// </summary>
        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();
            }
        }
    
        /// <summary>
        /// 停止状态
        /// </summary>
        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("电梯停止了...");
            }
        }
    
        /// <summary>
        /// 上下文类
        /// </summary>
        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
    {
        /// <summary>
        /// 抽象存款状态
        /// </summary>
        public abstract class State
        {
            protected Account context;
            public Account Context
            {
                set { context = value; }
            }
    
            /// <summary>
            /// 余额
            /// </summary
            public double Balance { get; set; }
            /// <summary>
            /// 利率
            /// </summary>
            public double Interest { get; set; }
            /// <summary>
            /// 下限
            /// </summary>
            public double LowerLimit { get; set; }
            /// <summary>
            /// 上限
            /// </summary>
            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;
                }
            }
    
        }
    
        /// <summary>
        /// Red State意味着Account透支
        /// </summary>
        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()
            {
                // 没有利息
            }
        }
    
        /// <summary>
        /// Silver State意味着没有利息得
        /// </summary>
        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;
                }
            }
        }
    
        /// <summary>
        /// Gold State意味着有利息状态
        /// </summary>
        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;
                }
            }
    
    
        }
    
        /// <summary>
        /// 上下文类
        /// </summary>
        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
  • 相关阅读:
    HDU 1025 Constructing Roads In JGShining's Kingdom (DP+二分)
    HDU 1158 Employment Planning
    HDU 2059 龟兔赛跑
    Csharp 简单操作Word模板文件
    Csharp windowform datagridview Clipboard TO EXCEL OR FROM EXCEL DATA 保存datagridview所有數據
    Csharp 讀寫文件內容搜索自動彈出 AutoCompleteMode
    Csharp windowform controls clear
    CSS DIV大图片右上角叠加小图片
    Csharp DataGridView自定义添加DateTimePicker控件日期列
    Csharp 打印Word文件默認打印機或選擇打印機設置代碼
  • 原文地址:https://www.cnblogs.com/scmail81/p/8688645.html
Copyright © 2011-2022 走看看