- 浏览: 4200864 次
最新评论
Design Pattern - State (C#)
Definition
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
UML Class Diagram
Participants
The classes and/or objects participating in this pattern are:
-
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
Sample Code in C#
This structural code demonstrates the State pattern which allows an object to behave differently depending on its internal state. The difference in behavior is delegated to objects that represent this state.
// -------------------------------------------------------------------------------------------------------------------- // <copyright company="Chimomo's Company" file="Program.cs"> // Respect the work. // </copyright> // <summary> // Structural State Design Pattern. // </summary> // -------------------------------------------------------------------------------------------------------------------- namespace CSharpLearning { using System; /// <summary> /// Startup class for Structural State Design Pattern. /// </summary> internal static class Program { #region Methods /// <summary> /// Entry point into console application. /// </summary> private static void Main() { // Setup context in a state var c = new Context(new ConcreteStateA()); // Issue requests, which toggles state c.Request(); c.Request(); c.Request(); c.Request(); } #endregion } /// <summary> /// The 'State' abstract class /// </summary> internal abstract class State { #region Public Methods and Operators /// <summary> /// The handle. /// </summary> /// <param name="context"> /// The context. /// </param> public abstract void Handle(Context context); #endregion } /// <summary> /// A 'ConcreteState' class /// </summary> internal class ConcreteStateA : State { #region Public Methods and Operators /// <summary> /// The handle. /// </summary> /// <param name="context"> /// The context. /// </param> public override void Handle(Context context) { context.State = new ConcreteStateB(); } #endregion } /// <summary> /// A 'ConcreteState' class /// </summary> internal class ConcreteStateB : State { #region Public Methods and Operators /// <summary> /// The handle. /// </summary> /// <param name="context"> /// The context. /// </param> public override void Handle(Context context) { context.State = new ConcreteStateA(); } #endregion } /// <summary> /// The 'Context' class /// </summary> internal class Context { #region Fields /// <summary> /// The state. /// </summary> private State state; #endregion // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="state"> /// The state. /// </param> public Context(State state) { this.State = state; } #endregion // Gets or sets the state #region Public Properties /// <summary> /// Gets or sets the state. /// </summary> public State State { get { return this.state; } set { this.state = value; Console.WriteLine("State: " + this.state.GetType().Name); } } #endregion #region Public Methods and Operators /// <summary> /// The request. /// </summary> public void Request() { this.state.Handle(this); } #endregion } } // Output: /* State: ConcreteStateA State: ConcreteStateB State: ConcreteStateA State: ConcreteStateB State: ConcreteStateA */
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.
// -------------------------------------------------------------------------------------------------------------------- // <copyright company="Chimomo's Company" file="Program.cs"> // Respect the work. // </copyright> // <summary> // Real-World State Design Pattern. // </summary> // -------------------------------------------------------------------------------------------------------------------- namespace CSharpLearning { using System; /// <summary> /// Startup class for Real-World State Design Pattern. /// </summary> internal static class Program { #region Methods /// <summary> /// Entry point into console application. /// </summary> private static void Main() { // Open a new account var 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); } #endregion } /// <summary> /// The 'State' abstract class /// </summary> internal abstract class State { #region Fields /// <summary> /// The account. /// </summary> protected Account account; /// <summary> /// The balance. /// </summary> protected double balance; /// <summary> /// The interest. /// </summary> protected double interest; /// <summary> /// The lower limit. /// </summary> protected double lowerLimit; /// <summary> /// The upper limit. /// </summary> protected double upperLimit; #endregion // Properties #region Public Properties /// <summary> /// Gets or sets the account. /// </summary> public Account Account { get { return this.account; } set { this.account = value; } } /// <summary> /// Gets or sets the balance. /// </summary> public double Balance { get { return this.balance; } set { this.balance = value; } } #endregion #region Public Methods and Operators /// <summary> /// The deposit. /// </summary> /// <param name="amount"> /// The amount. /// </param> public abstract void Deposit(double amount); /// <summary> /// The pay interest. /// </summary> public abstract void PayInterest(); /// <summary> /// The withdraw. /// </summary> /// <param name="amount"> /// The amount. /// </param> public abstract void Withdraw(double amount); #endregion } /// <summary> /// A 'ConcreteState' class /// <remarks> /// Red indicates that account is overdrawn /// </remarks> /// </summary> internal class RedState : State { #region Fields /// <summary> /// The service fee. /// </summary> private double serviceFee; #endregion // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="RedState"/> class. /// </summary> /// <param name="state"> /// The state. /// </param> public RedState(State state) { this.balance = state.Balance; this.account = state.Account; this.Initialize(); } #endregion #region Public Methods and Operators /// <summary> /// The deposit. /// </summary> /// <param name="amount"> /// The amount. /// </param> public override void Deposit(double amount) { this.balance += amount; this.StateChangeCheck(); } /// <summary> /// The pay interest. /// </summary> public override void PayInterest() { // No interest is paid } /// <summary> /// The withdraw. /// </summary> /// <param name="amount"> /// The amount. /// </param> public override void Withdraw(double amount) { amount = amount - this.serviceFee; Console.WriteLine("No funds available for withdrawal!"); } #endregion #region Methods /// <summary> /// The initialize. /// </summary> private void Initialize() { // Should come from a data source. this.interest = 0.0; this.lowerLimit = -100.0; this.upperLimit = 0.0; this.serviceFee = 15.00; } /// <summary> /// The state change check. /// </summary> private void StateChangeCheck() { if (this.balance > this.upperLimit) { this.account.State = new SilverState(this); } } #endregion } /// <summary> /// A 'ConcreteState' class /// <remarks> /// Silver indicates a non-interest bearing state /// </remarks> /// </summary> internal class SilverState : State { // Overloaded constructors #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="SilverState"/> class. /// </summary> /// <param name="state"> /// The state. /// </param> public SilverState(State state) : this(state.Balance, state.Account) { } /// <summary> /// Initializes a new instance of the <see cref="SilverState"/> class. /// </summary> /// <param name="balance"> /// The balance. /// </param> /// <param name="account"> /// The account. /// </param> public SilverState(double balance, Account account) { this.balance = balance; this.account = account; this.Initialize(); } #endregion #region Public Methods and Operators /// <summary> /// The deposit. /// </summary> /// <param name="amount"> /// The amount. /// </param> public override void Deposit(double amount) { this.balance += amount; this.StateChangeCheck(); } /// <summary> /// The pay interest. /// </summary> public override void PayInterest() { this.balance += this.interest * this.balance; this.StateChangeCheck(); } /// <summary> /// The withdraw. /// </summary> /// <param name="amount"> /// The amount. /// </param> public override void Withdraw(double amount) { this.balance -= amount; this.StateChangeCheck(); } #endregion #region Methods /// <summary> /// The initialize. /// </summary> private void Initialize() { // Should come from a data source. this.interest = 0.0; this.lowerLimit = 0.0; this.upperLimit = 1000.0; } /// <summary> /// The state change check. /// </summary> private void StateChangeCheck() { if (this.balance < this.lowerLimit) { this.account.State = new RedState(this); } else if (this.balance > this.upperLimit) { this.account.State = new GoldState(this); } } #endregion } /// <summary> /// A 'ConcreteState' class /// <remarks> /// Gold indicates an interest bearing state /// </remarks> /// </summary> internal class GoldState : State { // Overloaded constructors #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="GoldState"/> class. /// </summary> /// <param name="state"> /// The state. /// </param> public GoldState(State state) : this(state.Balance, state.Account) { } /// <summary> /// Initializes a new instance of the <see cref="GoldState"/> class. /// </summary> /// <param name="balance"> /// The balance. /// </param> /// <param name="account"> /// The account. /// </param> public GoldState(double balance, Account account) { this.balance = balance; this.account = account; this.Initialize(); } #endregion #region Public Methods and Operators /// <summary> /// The deposit. /// </summary> /// <param name="amount"> /// The amount. /// </param> public override void Deposit(double amount) { this.balance += amount; this.StateChangeCheck(); } /// <summary> /// The pay interest. /// </summary> public override void PayInterest() { this.balance += this.interest * this.balance; this.StateChangeCheck(); } /// <summary> /// The withdraw. /// </summary> /// <param name="amount"> /// The amount. /// </param> public override void Withdraw(double amount) { this.balance -= amount; this.StateChangeCheck(); } #endregion #region Methods /// <summary> /// The initialize. /// </summary> private void Initialize() { // Should come from a database this.interest = 0.05; this.lowerLimit = 1000.0; this.upperLimit = 10000000.0; } /// <summary> /// The state change check. /// </summary> private void StateChangeCheck() { if (this.balance < 0.0) { this.account.State = new RedState(this); } else if (this.balance < this.lowerLimit) { this.account.State = new SilverState(this); } } #endregion } /// <summary> /// The 'Context' class /// </summary> internal class Account { #region Fields /// <summary> /// The owner. /// </summary> private string owner; /// <summary> /// The state. /// </summary> private State state; #endregion // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="Account"/> class. /// </summary> /// <param name="owner"> /// The owner. /// </param> public Account(string owner) { // New accounts are 'Silver' by default this.owner = owner; this.state = new SilverState(0.0, this); } #endregion // Properties #region Public Properties /// <summary> /// Gets the balance. /// </summary> public double Balance { get { return this.state.Balance; } } /// <summary> /// Gets or sets the state. /// </summary> public State State { get { return this.state; } set { this.state = value; } } #endregion #region Public Methods and Operators /// <summary> /// The deposit. /// </summary> /// <param name="amount"> /// The amount. /// </param> public void Deposit(double amount) { this.state.Deposit(amount); Console.WriteLine("Deposited {0:C} --- ", amount); Console.WriteLine(" Balance = {0:C}", this.Balance); Console.WriteLine(" Status = {0}", this.State.GetType().Name); Console.WriteLine(string.Empty); } /// <summary> /// The pay interest. /// </summary> public void PayInterest() { this.state.PayInterest(); Console.WriteLine("Interest Paid --- "); Console.WriteLine(" Balance = {0:C}", this.Balance); Console.WriteLine(" Status = {0}\n", this.State.GetType().Name); } /// <summary> /// The withdraw. /// </summary> /// <param name="amount"> /// The amount. /// </param> public void Withdraw(double amount) { this.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); } #endregion } } // Output: /* Deposited $500.00 --- Balance = $500.00 Status = SilverState Deposited $300.00 --- Balance = $800.00 Status = SilverState Deposited $550.00 --- Balance = $1,350.00 Status = GoldState Interest Paid --- Balance = $1,417.50 Status = GoldState Withdrew $2,000.00 --- Balance = ($582.50) Status = RedState No funds available for withdrawal! Withdrew $1,100.00 --- Balance = ($582.50) Status = RedState */
相关推荐
design-pattern-java.pdf
Design pattern In JavaScrip-design-pattern-in-javascript
JAVA design pattern-java设计模式.chm
C++11全套设计模式-23种指针的用法(a full DesignPattern -DesignPattern
十一个行为型模式 状态模式-State Pattern 处理对象的多种状态及其相互转换——状态模式(一) 处理对象的多种状态及其相互转换——状态模式(二) 处理对象的多种状态及其相互转换——状态模式(三) 处理对象的...
design-pattern-java
DESIGN PATTERN - Pro Design Patterns in Swift,學習移動開發原始碼最佳選擇
个人觉得这本书介绍的设计模式知识比较通俗易懂
课程作业,adapter pattern基本演示
23种设计模式的C++实现DesignPattern-master.zip
design-pattern-demo
设计面向对象软件比较困难,而设计可复用的面向对象软件就更加困难。你必须找到相 关的对象,以适当的粒度将它们归类,再定义类的接口和继承层次,建立对象之间的基本关 系。你的设计应该对手头的问题有针对性,同时...
设计模式pdf
when it can be applied in view of other design constraints, and the consequences and trade-offs of using the pattern within a larger design. All patterns are compiled from real systems and are based ...
23种设计模式
Unity-Design-Pattern-master.zip.zip
经典的Java模式,工厂模式、单例模式,非常有助于初学者的学习
save document! UML file for the design pattern.
设计模式/design-pattern-lessons.pdf,设计模式包交不包会
Joint-Radar-and-Communication-Design-Applications-State-of-the-A