状态模式(State Pattern)

设计模式 - 吕震宇

.NET设计模式系列文章

薛敬明的专栏

乐在其中设计模式(C#)

设计模式24:State Pattern (状态模式)

英文原文:http://www.dofactory.com/Patterns/PatternState.aspx

一、State Pattern (状态模式)

Define: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

定义:当一个对象的内部状态进行改变的时候允许对象改变其行为。这个对象将显然可以改变其类。

二、UML类图

  • Context  (Account)
    • defines the interface of interest to clients
    • maintains an instance of a ConcreteState subclass that defines the current state.
  • State  (State)
    • defines an interface for encapsulating the behavior associated with a particular state of the Context.
  • Concrete State  (RedState, SilverState, GoldState)
    • each subclass implements a behavior associated with a state of Context

    三、State Pattern (状态模式)实例性代码

    [c-sharp] view plain copy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5.   
    6. namespace State_Pattern  
    7. {  
    8.     /// <summary>  
    9.   
    10.     /// MainApp startup class for Structural  
    11.   
    12.     /// State Design Pattern.  
    13.   
    14.     /// </summary>  
    15.   
    16.     class MainApp  
    17.     {  
    18.   
    19.         /// <summary>  
    20.   
    21.         /// Entry point into console application.  
    22.   
    23.         /// </summary>  
    24.   
    25.         static void Main()  
    26.         {  
    27.   
    28.             // Setup context in a state  
    29.   
    30.             Context c = new Context(new ConcreteStateA());  
    31.   
    32.   
    33.   
    34.             // Issue requests, which toggles state  
    35.   
    36.             c.Request();  
    37.   
    38.             c.Request();  
    39.   
    40.             c.Request();  
    41.   
    42.             c.Request();  
    43.   
    44.   
    45.   
    46.             // Wait for user  
    47.   
    48.             Console.ReadKey();  
    49.   
    50.         }  
    51.   
    52.     }  
    53.   
    54.   
    55.   
    56.     /// <summary>  
    57.   
    58.     /// The 'State' abstract class  
    59.   
    60.     /// </summary>  
    61.   
    62.     abstract class State  
    63.     {  
    64.   
    65.         public abstract void Handle(Context context);  
    66.   
    67.     }  
    68.   
    69.   
    70.   
    71.     /// <summary>  
    72.   
    73.     /// A 'ConcreteState' class  
    74.   
    75.     /// </summary>  
    76.   
    77.     class ConcreteStateA : State  
    78.     {  
    79.   
    80.         public override void Handle(Context context)  
    81.         {  
    82.   
    83.             context.State = new ConcreteStateB();  
    84.   
    85.         }  
    86.   
    87.     }  
    88.   
    89.   
    90.   
    91.     /// <summary>  
    92.   
    93.     /// A 'ConcreteState' class  
    94.   
    95.     /// </summary>  
    96.   
    97.     class ConcreteStateB : State  
    98.     {  
    99.   
    100.         public override void Handle(Context context)  
    101.         {  
    102.   
    103.             context.State = new ConcreteStateA();  
    104.   
    105.         }  
    106.   
    107.     }  
    108.   
    109.   
    110.   
    111.     /// <summary>  
    112.   
    113.     /// The 'Context' class  
    114.   
    115.     /// </summary>  
    116.   
    117.     class Context  
    118.     {  
    119.   
    120.         private State _state;  
    121.   
    122.   
    123.   
    124.         // Constructor  
    125.   
    126.         public Context(State state)  
    127.         {  
    128.   
    129.             this.State = state;  
    130.   
    131.         }  
    132.   
    133.   
    134.   
    135.         // Gets or sets the state  
    136.   
    137.         public State State  
    138.         {  
    139.   
    140.             get { return _state; }  
    141.   
    142.             set  
    143.             {  
    144.   
    145.                 _state = value;  
    146.   
    147.                 Console.WriteLine("State: " +  
    148.   
    149.                   _state.GetType().Name);  
    150.   
    151.             }  
    152.   
    153.         }  
    154.   
    155.   
    156.   
    157.         public void Request()  
    158.         {  
    159.   
    160.             _state.Handle(this);  
    161.   
    162.         }  
    163.   
    164.     }  
    165. }  

    四、使用State Pattern (状态模式)的实例代码

    This real-world code demonstrates the State pattern which allows an Account to behave differently depending on its balance. The difference in behavior is delegated to State objects called RedState, SilverState and GoldState. These states represent overdrawn accounts, starter accounts, and accounts in good standing.

    [c-sharp] view plain copy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5.   
    6. namespace State_Pattern  
    7. {  
    8.     /// <summary>  
    9.   
    10.     /// MainApp startup class for Real-World   
    11.   
    12.     /// State Design Pattern.  
    13.   
    14.     /// </summary>  
    15.   
    16.     class MainApp  
    17.     {  
    18.   
    19.         /// <summary>  
    20.   
    21.         /// Entry point into console application.  
    22.   
    23.         /// </summary>  
    24.   
    25.         static void Main()  
    26.         {  
    27.   
    28.             // Open a new account  
    29.   
    30.             Account account = new Account("Jim Johnson");  
    31.   
    32.   
    33.   
    34.             // Apply financial transactions  
    35.   
    36.             account.Deposit(500.0);  
    37.   
    38.             account.Deposit(300.0);  
    39.   
    40.             account.Deposit(550.0);  
    41.   
    42.             account.PayInterest();  
    43.   
    44.             account.Withdraw(2000.00);  
    45.   
    46.             account.Withdraw(1100.00);  
    47.   
    48.   
    49.   
    50.             // Wait for user  
    51.   
    52.             Console.ReadKey();  
    53.   
    54.         }  
    55.   
    56.     }  
    57.   
    58.   
    59.   
    60.     /// <summary>  
    61.   
    62.     /// The 'State' abstract class  
    63.   
    64.     /// </summary>  
    65.   
    66.     abstract class State  
    67.     {  
    68.   
    69.         protected Account account;  
    70.   
    71.         protected double balance;  
    72.   
    73.   
    74.   
    75.         protected double interest;  
    76.   
    77.         protected double lowerLimit;  
    78.   
    79.         protected double upperLimit;  
    80.   
    81.   
    82.   
    83.         // Properties  
    84.   
    85.         public Account Account  
    86.         {  
    87.   
    88.             get { return account; }  
    89.   
    90.             set { account = value; }  
    91.   
    92.         }  
    93.   
    94.   
    95.   
    96.         public double Balance  
    97.         {  
    98.   
    99.             get { return balance; }  
    100.   
    101.             set { balance = value; }  
    102.   
    103.         }  
    104.   
    105.   
    106.   
    107.         public abstract void Deposit(double amount);  
    108.   
    109.         public abstract void Withdraw(double amount);  
    110.   
    111.         public abstract void PayInterest();  
    112.   
    113.     }  
    114.   
    115.   
    116.   
    117.   
    118.   
    119.     /// <summary>  
    120.   
    121.     /// A 'ConcreteState' class  
    122.   
    123.     /// <remarks>  
    124.   
    125.     /// Red indicates that account is overdrawn   
    126.   
    127.     /// </remarks>  
    128.   
    129.     /// </summary>  
    130.   
    131.     class RedState : State  
    132.     {  
    133.   
    134.         private double _serviceFee;  
    135.   
    136.   
    137.   
    138.         // Constructor  
    139.   
    140.         public RedState(State state)  
    141.         {  
    142.   
    143.             this.balance = state.Balance;  
    144.   
    145.             this.account = state.Account;  
    146.   
    147.             Initialize();  
    148.   
    149.         }  
    150.   
    151.   
    152.   
    153.         private void Initialize()  
    154.         {  
    155.   
    156.             // Should come from a datasource  
    157.   
    158.             interest = 0.0;  
    159.   
    160.             lowerLimit = -100.0;  
    161.   
    162.             upperLimit = 0.0;  
    163.   
    164.             _serviceFee = 15.00;  
    165.   
    166.         }  
    167.   
    168.   
    169.   
    170.         public override void Deposit(double amount)  
    171.         {  
    172.   
    173.             balance += amount;  
    174.   
    175.             StateChangeCheck();  
    176.   
    177.         }  
    178.   
    179.   
    180.   
    181.         public override void Withdraw(double amount)  
    182.         {  
    183.   
    184.             amount = amount - _serviceFee;  
    185.   
    186.             Console.WriteLine("No funds available for withdrawal!");  
    187.   
    188.         }  
    189.   
    190.   
    191.   
    192.         public override void PayInterest()  
    193.         {  
    194.   
    195.             // No interest is paid  
    196.   
    197.         }  
    198.   
    199.   
    200.   
    201.         private void StateChangeCheck()  
    202.         {  
    203.   
    204.             if (balance > upperLimit)  
    205.             {  
    206.   
    207.                 account.State = new SilverState(this);  
    208.   
    209.             }  
    210.   
    211.         }  
    212.   
    213.     }  
    214.   
    215.   
    216.   
    217.     /// <summary>  
    218.   
    219.     /// A 'ConcreteState' class  
    220.   
    221.     /// <remarks>  
    222.   
    223.     /// Silver indicates a non-interest bearing state  
    224.   
    225.     /// </remarks>  
    226.   
    227.     /// </summary>  
    228.   
    229.     class SilverState : State  
    230.     {  
    231.   
    232.         // Overloaded constructors  
    233.   
    234.   
    235.   
    236.         public SilverState(State state) :  
    237.   
    238.             this(state.Balance, state.Account)  
    239.         {  
    240.   
    241.         }  
    242.   
    243.   
    244.   
    245.         public SilverState(double balance, Account account)  
    246.         {  
    247.   
    248.             this.balance = balance;  
    249.   
    250.             this.account = account;  
    251.   
    252.             Initialize();  
    253.   
    254.         }  
    255.   
    256.   
    257.   
    258.         private void Initialize()  
    259.         {  
    260.   
    261.             // Should come from a datasource  
    262.   
    263.             interest = 0.0;  
    264.   
    265.             lowerLimit = 0.0;  
    266.   
    267.             upperLimit = 1000.0;  
    268.   
    269.         }  
    270.   
    271.   
    272.   
    273.         public override void Deposit(double amount)  
    274.         {  
    275.   
    276.             balance += amount;  
    277.   
    278.             StateChangeCheck();  
    279.   
    280.         }  
    281.   
    282.   
    283.   
    284.         public override void Withdraw(double amount)  
    285.         {  
    286.   
    287.             balance -= amount;  
    288.   
    289.             StateChangeCheck();  
    290.   
    291.         }  
    292.   
    293.   
    294.   
    295.         public override void PayInterest()  
    296.         {  
    297.   
    298.             balance += interest * balance;  
    299.   
    300.             StateChangeCheck();  
    301.   
    302.         }  
    303.   
    304.   
    305.   
    306.         private void StateChangeCheck()  
    307.         {  
    308.   
    309.             if (balance < lowerLimit)  
    310.             {  
    311.   
    312.                 account.State = new RedState(this);  
    313.   
    314.             }  
    315.   
    316.             else if (balance > upperLimit)  
    317.             {  
    318.   
    319.                 account.State = new GoldState(this);  
    320.   
    321.             }  
    322.   
    323.         }  
    324.   
    325.     }  
    326.   
    327.   
    328.   
    329.     /// <summary>  
    330.   
    331.     /// A 'ConcreteState' class  
    332.   
    333.     /// <remarks>  
    334.   
    335.     /// Gold indicates an interest bearing state  
    336.   
    337.     /// </remarks>  
    338.   
    339.     /// </summary>  
    340.   
    341.     class GoldState : State  
    342.     {  
    343.   
    344.         // Overloaded constructors  
    345.   
    346.         public GoldState(State state)  
    347.   
    348.             : this(state.Balance, state.Account)  
    349.         {  
    350.   
    351.         }  
    352.   
    353.   
    354.   
    355.         public GoldState(double balance, Account account)  
    356.         {  
    357.   
    358.             this.balance = balance;  
    359.   
    360.             this.account = account;  
    361.   
    362.             Initialize();  
    363.   
    364.         }  
    365.   
    366.   
    367.   
    368.         private void Initialize()  
    369.         {  
    370.   
    371.             // Should come from a database  
    372.   
    373.             interest = 0.05;  
    374.   
    375.             lowerLimit = 1000.0;  
    376.   
    377.             upperLimit = 10000000.0;  
    378.   
    379.         }  
    380.   
    381.   
    382.   
    383.         public override void Deposit(double amount)  
    384.         {  
    385.   
    386.             balance += amount;  
    387.   
    388.             StateChangeCheck();  
    389.   
    390.         }  
    391.   
    392.   
    393.   
    394.         public override void Withdraw(double amount)  
    395.         {  
    396.   
    397.             balance -= amount;  
    398.   
    399.             StateChangeCheck();  
    400.   
    401.         }  
    402.   
    403.   
    404.   
    405.         public override void PayInterest()  
    406.         {  
    407.   
    408.             balance += interest * balance;  
    409.   
    410.             StateChangeCheck();  
    411.   
    412.         }  
    413.   
    414.   
    415.   
    416.         private void StateChangeCheck()  
    417.         {  
    418.   
    419.             if (balance < 0.0)  
    420.             {  
    421.   
    422.                 account.State = new RedState(this);  
    423.   
    424.             }  
    425.   
    426.             else if (balance < lowerLimit)  
    427.             {  
    428.   
    429.                 account.State = new SilverState(this);  
    430.   
    431.             }  
    432.   
    433.         }  
    434.   
    435.     }  
    436.   
    437.   
    438.   
    439.     /// <summary>  
    440.   
    441.     /// The 'Context' class  
    442.   
    443.     /// </summary>  
    444.   
    445.     class Account  
    446.     {  
    447.   
    448.         private State _state;  
    449.   
    450.         private string _owner;  
    451.   
    452.   
    453.   
    454.         // Constructor  
    455.   
    456.         public Account(string owner)  
    457.         {  
    458.   
    459.             // New accounts are 'Silver' by default  
    460.   
    461.             this._owner = owner;  
    462.   
    463.             this._state = new SilverState(0.0, this);  
    464.   
    465.         }  
    466.   
    467.   
    468.   
    469.         // Properties  
    470.   
    471.         public double Balance  
    472.         {  
    473.   
    474.             get { return _state.Balance; }  
    475.   
    476.         }  
    477.   
    478.   
    479.   
    480.         public State State  
    481.         {  
    482.   
    483.             get { return _state; }  
    484.   
    485.             set { _state = value; }  
    486.   
    487.         }  
    488.   
    489.   
    490.   
    491.         public void Deposit(double amount)  
    492.         {  
    493.   
    494.             _state.Deposit(amount);  
    495.   
    496.             Console.WriteLine("Deposited {0:C} --- ", amount);  
    497.   
    498.             Console.WriteLine(" Balance = {0:C}"this.Balance);  
    499.   
    500.             Console.WriteLine(" Status = {0}",  
    501.   
    502.               this.State.GetType().Name);  
    503.   
    504.             Console.WriteLine("");  
    505.   
    506.         }  
    507.   
    508.   
    509.   
    510.         public void Withdraw(double amount)  
    511.         {  
    512.   
    513.             _state.Withdraw(amount);  
    514.   
    515.             Console.WriteLine("Withdrew {0:C} --- ", amount);  
    516.   
    517.             Console.WriteLine(" Balance = {0:C}"this.Balance);  
    518.   
    519.             Console.WriteLine(" Status = {0}/n",  
    520.   
    521.               this.State.GetType().Name);  
    522.   
    523.         }  
    524.   
    525.   
    526.   
    527.         public void PayInterest()  
    528.         {  
    529.   
    530.             _state.PayInterest();  
    531.   
    532.             Console.WriteLine("Interest Paid --- ");  
    533.   
    534.             Console.WriteLine(" Balance = {0:C}"this.Balance);  
    535.   
    536.             Console.WriteLine(" Status = {0}/n",  
    537.   
    538.               this.State.GetType().Name);  
    539.   
    540.         }  
    541.   
    542.     }  
    543. }  


    乐在其中设计模式(C#) - 状态模式(State Pattern)

    介绍
    允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。


    示例
    有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里。在对象内部可以根据用户的不同选择不同的数据持久化方案。
    状态模式(State Pattern)_第1张图片


    MessageModel

    using  System;
    using  System.Collections.Generic;
    using  System.Text;

    namespace  Pattern.State
    {
        
    /// <summary>
        
    /// Message实体类
        
    /// </summary>

        public class MessageModel
        
    {
            
    /// <summary>
            
    /// 构造函数
            
    /// </summary>
            
    /// <param name="msg">Message内容</param>
            
    /// <param name="pt">Message发布时间</param>

            public MessageModel(string msg, DateTime pt)
            
    {
                
    this._message = msg;
                
    this._publishTime = pt;
            }


            
    private string _message;
            
    /// <summary>
            
    /// Message内容
            
    /// </summary>

            public string Message
            
    {
                
    get return _message; }
                
    set { _message = value; }
            }


            
    private DateTime _publishTime;
            
    /// <summary>
            
    /// Message发布时间
            
    /// </summary>

            public DateTime PublishTime
            
    {
                
    get return _publishTime; }
                
    set { _publishTime = value; }
            }

        }

    }


    AbstractMessageState
    using  System;
    using  System.Collections.Generic;
    using  System.Text;

    namespace  Pattern.State
    {
        
    /// <summary>
        
    /// 状态模式抽象类
        
    /// </summary>

        public abstract class AbstractMessageState
        
    {
            
    /// <summary>
            
    /// Context类型
            
    /// </summary>

            protected Message _message;

            
    /// <summary>
            
    /// Context类型属性
            
    /// </summary>

            public Message Message
            
    {
                
    get return _message; }
                
    set { _message = value; }
            }


            
    /// <summary>
            
    /// 改变状态
            
    /// </summary>

            public abstract void StateChangeCheck();

            
    /// <summary>
            
    /// 获取Message
            
    /// </summary>
            
    /// <returns></returns>

            public abstract List<MessageModel> Get();

            
    /// <summary>
            
    /// 插入Message
            
    /// </summary>
            
    /// <param name="mm">Message实体对象</param>
            
    /// <returns></returns>

            public abstract bool Insert(MessageModel mm);
        }

    }


    XmlMessage
    using  System;
    using  System.Collections.Generic;
    using  System.Text;

    namespace  Pattern.State
    {
        
    /// <summary>
        
    /// Xml方式操作Message
        
    /// </summary>

        public class XmlMessage : AbstractMessageState
        
    {
            
    /// <summary>
            
    /// 构造函数
            
    /// </summary>
            
    /// <param name="message">Context类型参数</param>

            public XmlMessage(Message message)
            
    {
                
    this._message = message;
            }


            
    /// <summary>
            
    /// 改变状态
            
    /// </summary>

            public override void StateChangeCheck()
            
    {
                
    // 如果UserId是admin则变换状态为SqlMessage
                if (this._message.UserId == "admin")
                
    {
                    
    this._message.AbstractMessageState = new SqlMessage(this._message);
                }

            }


            
    /// <summary>
            
    /// 获取Message
            
    /// </summary>
            
    /// <returns></returns>

            public override List<MessageModel> Get()
            
    {
                List
    <MessageModel> l = new List<MessageModel>();
                l.Add(
    new MessageModel("XML方式获取Message", DateTime.Now));

                
    return l;
            }


            
    /// <summary>
            
    /// 插入Message
            
    /// </summary>
            
    /// <param name="mm">Message实体对象</param>
            
    /// <returns></returns>

            public override bool Insert(MessageModel mm)
            
    {
                
    // 代码略
                return true;
            }

        }

    }


    SqlMessage
    using  System;
    using  System.Collections.Generic;
    using  System.Text;

    namespace  Pattern.State
    {
        
    /// <summary>
        
    /// Sql方式操作Message
        
    /// </summary>

        public class SqlMessage : AbstractMessageState
        
    {
            
    /// <summary>
            
    /// 构造函数
            
    /// </summary>
            
    /// <param name="message">Context类型参数</param>

            public SqlMessage(Message message)
            
    {
                
    this._message = message;
            }


            
    /// <summary>
            
    /// 改变状态
            
    /// </summary>

            public override void StateChangeCheck()
            
    {

            }


            
    /// <summary>
            
    /// 获取Message
            
    /// </summary>
            
    /// <returns></returns>

            public override List<MessageModel> Get()
            
    {
                List
    <MessageModel> l = new List<MessageModel>();
                l.Add(
    new MessageModel("SQL方式获取Message", DateTime.Now));

                
    return l;
            }


            
    /// <summary>
            
    /// 插入Message
            
    /// </summary>
            
    /// <param name="mm">Message实体对象</param>
            
    /// <returns></returns>

            public override bool Insert(MessageModel mm)
            
    {
                
    // 代码略
                return true;
            }

        }

    }


    Message
    using  System;
    using  System.Collections.Generic;
    using  System.Text;

    namespace  Pattern.State
    {
        
    /// <summary>
        
    /// Context类
        
    /// </summary>

        public class Message
        
    {
            
    /// <summary>
            
    /// 类型为状态模式抽象类的私有变量
            
    /// </summary>

            private AbstractMessageState _abstractMessageState;

            
    /// <summary>
            
    /// 类型为状态模式抽象类的属性
            
    /// </summary>

            public AbstractMessageState AbstractMessageState
            
    {
                
    get return _abstractMessageState; }
                
    set { _abstractMessageState = value; }
            }
           

            
    /// <summary>
            
    /// UserId私有变量
            
    /// </summary>

            private string _userId;

            
    /// <summary>
            
    /// UserId
            
    /// </summary>

            public string UserId
            
    {
                
    get return _userId; }
                
    set { _userId = value; }
            }


            
    /// <summary>
            
    /// 构造函数
            
    /// </summary>
            
    /// <param name="userId">UserId</param>

            public Message(string userId)
            
    {
                
    this._userId = userId;

                _abstractMessageState 
    = new XmlMessage(this);
            }


            
    /// <summary>
            
    /// 获取Message
            
    /// </summary>
            
    /// <returns></returns>

            public List<MessageModel> Get()
            
    {
                
    // 修改状态
                _abstractMessageState.StateChangeCheck();

                
    return _abstractMessageState.Get();
            }


            
    /// <summary>
            
    /// 插入Message
            
    /// </summary>
            
    /// <param name="mm">Message实体对象</param>
            
    /// <returns></returns>

            public bool Insert(MessageModel mm)
            
    {
                
    // 修改状态
                _abstractMessageState.StateChangeCheck();

                
    return _abstractMessageState.Insert(mm);
            }

        }

    }



    client
    using  System;
    using  System.Data;
    using  System.Configuration;
    using  System.Collections;
    using  System.Web;
    using  System.Web.Security;
    using  System.Web.UI;
    using  System.Web.UI.WebControls;
    using  System.Web.UI.WebControls.WebParts;
    using  System.Web.UI.HtmlControls;

    using  Pattern.State;

    public  partial  class  State : System.Web.UI.Page
    {
        
    protected void Page_Load(object sender, EventArgs e)
        
    {
            Message m 
    = new Message("admin");
            Response.Write(m.Insert(
    new MessageModel("插入", DateTime.Now)));
            Response.Write(
    "<br />");
            Response.Write(m.Get()[
    0].Message + " " + m.Get()[0].PublishTime.ToString());
            Response.Write(
    "<br />");

            m 
    = new Message("user");
            Response.Write(m.Insert(
    new MessageModel("插入", DateTime.Now)));
            Response.Write(
    "<br />");
            Response.Write(m.Get()[
    0].Message + " " + m.Get()[0].PublishTime.ToString());
            Response.Write(
    "<br />");
        }

    }


    运行结果
    True
    SQL方式获取Message 2007-3-6 22:58:17
    True
    XML方式获取Message 2007-3-6 22:58:17


    参考
    http://www.dofactory.com/Patterns/PatternState.aspx


    OK
    [源码下载]




  • 你可能感兴趣的:(状态模式(State Pattern))