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
  • 相关阅读:
    windows窗体中的一些事。。。
    数据库报错问题
    Winform程序调用WebService连接数据库心得
    浅谈RichTextBox在Windows Phone开发中的应用 [WP开发]
    WP7 独立存储
    安装 Visual Studio Async CTP
    C#中的弱引用(WeakReference)
    WP7开发积累
    2011.11.15
    c# 计算时间间隔
  • 原文地址:https://www.cnblogs.com/scmail81/p/8688645.html
Copyright © 2011-2022 走看看