• 状态模式(State Pattern)


    对象状态影响对象行为:
        对象拥有不同的状态,往往会行使不同的行为...
                      
    动机:
        在软件构建过程中,某些对象的状态如果改变以及其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
        如何在运行时根据对象的状态来透明更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?

    意图:
     允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。  ------《设计模式》GOF
    结构图:
       
    适用性:
        1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
    2.一个操作中含有庞大的多分支的等条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个分支放入一个独立的类中。这使得你可根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

    代码实现:
       


      
    class MainApp
      {
        
    static void Main()
        {
          
    // Open a new account
          Account account = new Account("Jim Johnson");

          
    // Apply financial transactions
          account.Deposit(500.0);
          account.Deposit(
    300.0);
          account.Deposit(
    550.0);
          account.PayInterest();
          account.Withdraw(
    2000.00);
          account.Withdraw(
    1100.00);

          
    // Wait for user
          Console.Read();
        }
      }

      
    // "State"

      
    abstract class State
      {
        
    protected Account account;
        
    protected double balance;

        
    protected double interest;
        
    protected double lowerLimit;
        
    protected double upperLimit;

        
    // Properties
        public Account Account
        {
          
    getreturn account; }
          
    set{ account = value; }
        }

        
    public double Balance
        {
          
    getreturn balance; }
          
    set{ balance = value; }
        }

        
    public abstract void Deposit(double amount);
        
    public abstract void Withdraw(double amount);
        
    public abstract void PayInterest();
      }

      
    // "ConcreteState"

      
    // Account is overdrawn

      
    class RedState : State
      {
        
    double serviceFee;

        
    // Constructor
        public RedState(State state)
        {
          
    this.balance = state.Balance;
          
    this.account = state.Account;
          Initialize();
        }

        
    private void Initialize()
        {
          
    // Should come from a datasource
          interest = 0.0;
          lowerLimit 
    = -100.0;
          upperLimit 
    = 0.0;
          serviceFee 
    = 15.00;
        }

        
    public override void Deposit(double amount)
        {
          balance 
    += amount;
          StateChangeCheck();
        }

        
    public override void Withdraw(double amount)
        {
          amount 
    = amount - serviceFee;
          Console.WriteLine(
    "No funds available for withdrawal!");
        }

        
    public override void PayInterest()
        {
          
    // No interest is paid
        }

        
    private void StateChangeCheck()
        {
          
    if (balance > upperLimit)
          {
            account.State 
    = new SilverState(this);
          }
        }
      }

      
    // "ConcreteState"

      
    // Silver is non-interest bearing state

      
    class SilverState : State
      {
        
    // Overloaded constructors

        
    public SilverState(State state) :
          
    this( state.Balance, state.Account)
        {  
        }

        
    public SilverState(double balance, Account account)
        {
          
    this.balance = balance;
          
    this.account = account;
          Initialize();
        }

        
    private void Initialize()
        {
          
    // Should come from a datasource
          interest = 0.0;
          lowerLimit 
    = 0.0;
          upperLimit 
    = 1000.0;
        }

        
    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)
          {
            account.State 
    = new RedState(this);
          }
          
    else if (balance > upperLimit)
          {
            account.State 
    = new GoldState(this);
          }
        }
      }

      
    // "ConcreteState"

      
    // Interest bearing state

      
    class GoldState : State
      {
        
    // Overloaded constructors
        public GoldState(State state)
          : 
    this(state.Balance,state.Account)
        {  
        }

        
    public GoldState(double balance, Account account)
        {
          
    this.balance = balance;
          
    this.account = account;
          Initialize();
        }

        
    private void Initialize()
        {
          
    // Should come from a database
          interest = 0.05;
          lowerLimit 
    = 1000.0;
          upperLimit 
    = 10000000.0;
        }

        
    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)
          {
            account.State 
    = new RedState(this);
          }
          
    else if (balance < lowerLimit)
          {
            account.State 
    = new SilverState(this);
          }
        }
      }

      
    // "Context"

      
    class Account
      {
        
    private State state;
        
    private string owner;

        
    // Constructor
        public Account(string owner)
        {
          
    // New accounts are 'Silver' by default
          this.owner = owner;
          state 
    = new SilverState(0.0this);
        }

        
    // Properties
        public double Balance
        {
          
    getreturn state.Balance; }
        }

        
    public State State
        {
          
    getreturn state; }
          
    set{ state = value; }
        }

        
    public void Deposit(double amount)
        {
          state.Deposit(amount);
          Console.WriteLine(
    "Deposited {0:C} --- ", amount);
          Console.WriteLine(
    " Balance = {0:C}"this.Balance);
          Console.WriteLine(
    " Status = {0}\n" ,
            
    this.State.GetType().Name);
          Console.WriteLine(
    "");
        }

        
    public void Withdraw(double amount)
        {
          state.Withdraw(amount);
          Console.WriteLine(
    "Withdrew {0:C} --- ", amount);
          Console.WriteLine(
    " Balance = {0:C}"this.Balance);
          Console.WriteLine(
    " Status = {0}\n" ,
            
    this.State.GetType().Name);
        }

        
    public void PayInterest()
        {
          state.PayInterest();
          Console.WriteLine(
    "Interest Paid --- ");
          Console.WriteLine(
    " Balance = {0:C}"this.Balance);
          Console.WriteLine(
    " Status = {0}\n" ,
            
    this.State.GetType().Name);
        }
      }
    结果:
       
    State模式的几个要点:
        1.State模式将所有一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
        2.为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的----即要么彻底转换过来,要么不转换。
        3.如果State对象没有实例变量,那么各个上下文可以共享 同一个State对象,从而节省对象开销。
  • 相关阅读:
    聊聊自定义实现的SPI如何与spring进行整合
    聊聊读源码这件事
    聊聊自定义SPI如何使用自定义标签注入到spring容器中
    聊聊如何自定义数据脱敏
    聊聊自定义SPI如何与sentinel整合实现熔断限流
    排查not eligible for getting processed by all BeanPostProcessors
    SqlServer 数据脱敏脚本
    WPF 窗体使用 Show() 单个显示并设置弹窗相对于主窗体位置
    【SQLite】获取插入 ID 的几种方式
    Winform DataGridView 行单元格增加自定义 ToolTip
  • 原文地址:https://www.cnblogs.com/abcdwxc/p/910726.html
Copyright © 2020-2023  润新知