• 设计模式之状态模式


    状态模式类图:

     

    Context的request方法,根据自身的状态属性State, 执行state.handle方法,根据面向对象的多态原则,在运行时,由于可以动态修改Context的状态state,从而ConcreteState转化成另一个ConctreteState,执行各自的业务逻辑。

    我总结状态模式要注意以下几点:

    1. 在状态模式中,Context是持有状态的对象State,并可以修改状态setState.

    2. 但是Context并不处理跟状态相关的行为,而是把处理状态的功能委托给了ConctreteState类来处理。

    3. 在ConctreteState类中除了处理它的业务外,还要根据业务来修改Context的State,以达到修改状态的目的。(如果在Context中修改state就会有大量的if else)

    4. 客户端一般只和Context交互。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象。

     来看一下代码:

    假设银行账户的密码输入错误三次,账户状态改为Forbidden,如果输入错误6点,则locked.

    public class Account
        {
            private readonly string password = "123456";
    
            private int tryCount = 0;
    
            public Account()
            {
                // 账启初始化时为,normal状态
    
                this.State = new Normal(this);
            }
    
            public AccountState State { get; set; }
    
            public void Validate(string pwd)
            {
                if (pwd != password)
                {
                    tryCount++;
    
                    State.Show(tryCount);
                }
            }
    
        }
    
        public abstract class AccountState
        {
            protected Account account;
            protected int maxTryCount;
    
            public abstract void Show(int tryCount);
        }
    
        public class Normal : AccountState
        {
            public Normal(Account account)
            {
                this.account = account;
                maxTryCount = 2;
            }
    
            public override void Show(int tryCount)
            {
                Console.WriteLine("Account State is Normal");
                StateChange(tryCount);
            }
    
            private void StateChange(int tryCount)
            {
                if (tryCount >= maxTryCount)
                {
                    account.State = new Forbidden(this.account);
                }
            }
    
        }
    
        public class Forbidden : AccountState
        {
            public Forbidden(Account account) 
            {
                this.account = account;
                maxTryCount = 5;
            }
    
            public override void Show(int tryCount)
            {
                Console.WriteLine("Account State is Forbidden");
                StateChange(tryCount);
    
            }
    
            private void StateChange(int tryCount)
            {
                if (tryCount >= maxTryCount)
                {
                    account.State = new Locked(account);
                }
            }
    
        }
    
        public class Locked : AccountState
        {
            public Locked(Account account)
            {
            }
    
            public override void Show(int tryCount)
            {
                Console.WriteLine("Account State is Locked");
            }
    
        }
        class Program
        {
            static void Main(string[] args)
            {
                Account account = new Account();
    
                for (int i = 0; i < 6; i++)
                {
                    account.Validate("111111");
                }
    
                Console.ReadKey();
            }
        }

    个人的总结:

    1. 单纯的依靠状态模式没有很好的if else的问题,而且会产生大量的子类。

    2. 子类之间的相互耦合,有点不能让人接受,哪果业务有变化:输入错误10次,就报警,那不仅要加一个类,而且还要修改locked类,没有做到开闭原则。

       当然可以把状态的修改放在context里,通过 if else方式来处理,这样就可以做到开闭原则,但是又回到1的问题了。

  • 相关阅读:
    linux的常用命令--pwd命令【持续补充ing】
    linux的常用命令--cp命令【持续补充ing】
    linux的常用命令--mkdir【持续补充ing】
    linux的常用命令--su篇【持续补充ing】
    linux的常用命令--ls篇【持续补充ing】
    linux的常用命令--cd篇【持续补充ing】
    【SQL Server 2008数据库基础篇】常用关键字、数据类型和常用语法
    SpingBoot之多Profile文件
    SpringBoot之YAML
    SpringBoot之HelloWorld仔细分析
  • 原文地址:https://www.cnblogs.com/hankuikui/p/6995399.html
Copyright © 2020-2023  润新知