1、状态模式定义
允许对象在内部状态改变时,改变对象本身的行为,对象看起来好像修改了他的类。
2、要点
该模式将状态封装到独立的类里面,并将动作委托给代表当前状态的对象,行为就会随着内部状态的改变而改变。
从客户使用的角度来看,如果说我使用的对象完全改变了他的行为,那么客户会觉得这个对象时从另一个类实例化而来的。然而实际上,我们是通过组合通过简单引用不同的状态对象来造成类被改变的假象。
状态模式允许一个对象基于内部状态而拥有不同的行为
和程序状态机不同,状态模式用类代表状态
Contxet会将行为委托为当前状态
通过把每个状态封装进一个类,我们把以后需要做的任何改变局部化了
状态模式和策略模式类图相同,但意图不同,策略模式通常会用行为或算法来配置context类
状态模式允许context随着状态的改变而改变行为
状态装换可以由State类或Context类控制
使用状态模式通常会导致设计中类的数目大量增加
状态类可以被多个context实例共享。
3、例子代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StatePattern
{
public interface IState
{
/// <summary>
/// 投入硬币
/// </summary>
void insertQuarter();
/// <summary>
/// 退回硬币
/// </summary>
void ejectQuarter();
/// <summary>
/// 转动曲柄
/// </summary>
void turnCrank();
/// <summary>
/// 发放糖果
/// </summary>
void dispense();
}
/// <summary>
/// 售出状态
/// </summary>
public class SoldState : IState
{
private GumballMachine m_pMachine;
public SoldState(GumballMachine pMachine)
{
m_pMachine = pMachine;
}
#region IState 成员
public void insertQuarter()
{
Console.WriteLine("请等待下,机器目前正在售出糖果,还不能接收另外一次交易...");
}
public void ejectQuarter()
{
Console.WriteLine("已经无法退钱,机器目前正在售出糖果...");
}
public void turnCrank()
{
Console.WriteLine("机器目前正在售出糖果,无需再转动曲柄...");
}
public void dispense()
{
m_pMachine.deleteCount(1);
if (m_pMachine.GetCount() > 0)
{
m_pMachine.SetState(m_pMachine.GetNoQuarterState());
}
else
{
m_pMachine.SetState(m_pMachine.GetSoldOutState());
}
}
#endregion
}
/// <summary>
/// 售罄状态
/// </summary>
public class SoldOutState : IState
{
private GumballMachine m_pMachine;
public SoldOutState(GumballMachine pMachine)
{
m_pMachine = pMachine;
}
#region IState 成员
public void insertQuarter()
{
Console.WriteLine("机器目前为售罄状态,无法交易...");
}
public void ejectQuarter()
{
Console.WriteLine("机器目前为售罄状态,无法弹出硬币...");
}
public void turnCrank()
{
Console.WriteLine("机器目前为售罄状态,转动曲柄已经是只能锻炼你的臂力,除此之外啥也干不了...");
}
public void dispense()
{
Console.WriteLine("机器目前为售罄状态,无法发放糖果....");
}
#endregion
}
/// <summary>
/// 无硬币状态
/// </summary>
public class NoQuarterState : IState
{
private GumballMachine m_pMachine;
public NoQuarterState(GumballMachine pMachine)
{
m_pMachine = pMachine;
}
#region IState 成员
public void insertQuarter()
{
m_pMachine.SetState(m_pMachine.GetHasQuarterState());
}
public void ejectQuarter()
{
Console.WriteLine("机器目前为无硬币状态,无法弹出硬币...");
}
public void turnCrank()
{
Console.WriteLine("机器目前为无硬币状态,无法转动曲柄...");
}
public void dispense()
{
Console.WriteLine("机器目前为无硬币状态,无法发放糖果...");
}
#endregion
}
/// <summary>
/// 有硬币状态
/// </summary>
public class HasQuarterState : IState
{
private Random pRandom = new Random();
private GumballMachine m_pMachine;
public HasQuarterState(GumballMachine pMachine)
{
m_pMachine = pMachine;
}
#region IState 成员
public void insertQuarter()
{
Console.WriteLine("机器目前为有硬币状态,暂时无法投币...");
}
public void ejectQuarter()
{
m_pMachine.SetState(m_pMachine.GetNoQuarterState());
}
public void turnCrank()
{
if (pRandom.Next(0, 10) == 9 && m_pMachine.GetCount()>1)
m_pMachine.SetState(m_pMachine.GetWinnerState());
else
m_pMachine.SetState(m_pMachine.GetSoldState());
}
public void dispense()
{
Console.WriteLine("机器目前为有硬币状态,还未转动曲柄,无法执行发放糖果操作...");
}
#endregion
}
/// <summary>
/// 赢家状态
/// </summary>
public class WinnerState : IState
{
private GumballMachine m_pMachine;
public WinnerState(GumballMachine pMachine)
{
m_pMachine = pMachine;
}
#region IState 成员
public void insertQuarter()
{
Console.WriteLine("机器目前为赢家状态,暂时无法进行下一次交易...");
}
public void ejectQuarter()
{
Console.WriteLine("机器目前为赢家状态,无法退钱...");
}
public void turnCrank()
{
Console.WriteLine("机器目前为赢家状态,不必重复转动曲柄,等待机器吐出两颗糖果吧,Luck Man...");
}
public void dispense()
{
m_pMachine.deleteCount(2);
if (m_pMachine.GetCount() > 0)
{
m_pMachine.SetState(m_pMachine.GetNoQuarterState());
}
else
{
m_pMachine.SetState(m_pMachine.GetSoldOutState());
}
}
#endregion
}
/// <summary>
/// 糖果机
/// </summary>
public class GumballMachine
{
private IState m_SoldState = null;
private IState m_SoldOutState = null;
private IState m_NoQuarterState = null;
private IState m_HasQuarterState = null;
private IState m_WinnerState = null;
private IState m_state = null;
private int m_count = 0;
public GumballMachine(int count)
{
m_count = count;
m_SoldState = new SoldState(this);
m_SoldOutState = new SoldOutState(this);
m_NoQuarterState = new NoQuarterState(this);
m_HasQuarterState = new HasQuarterState(this);
m_WinnerState = new WinnerState(this);
if (m_count > 0)
m_state = m_NoQuarterState;
}
/// <summary>
/// 设置当前状态
/// </summary>
/// <param name="state"></param>
public void SetState(IState state)
{
m_state = state;
}
/// <summary>
/// 获取售出状态对象
/// </summary>
/// <returns></returns>
public IState GetSoldState()
{
return m_SoldState;
}
/// <summary>
/// 获取售罄状态对象
/// </summary>
/// <returns></returns>
public IState GetSoldOutState()
{
return m_SoldOutState;
}
/// <summary>
/// 获取未投币状态对象
/// </summary>
/// <returns></returns>
public IState GetNoQuarterState()
{
return m_NoQuarterState;
}
/// <summary>
/// 获取应投币状态对象
/// </summary>
/// <returns></returns>
public IState GetHasQuarterState()
{
return m_HasQuarterState;
}
/// <summary>
/// 获取赢家状态对象
/// </summary>
/// <returns></returns>
public IState GetWinnerState()
{
return m_WinnerState;
}
/// <summary>
/// 获取剩余糖果数目
/// </summary>
/// <returns></returns>
public int GetCount()
{
return m_count;
}
/// <summary>
/// 弹出糖果
/// </summary>
/// <param name="outputcount"></param>
public void deleteCount(int outputcount)
{
m_count -= outputcount;
}
/// <summary>
/// 投入硬币
/// </summary>
public void insertQuarter()
{
m_state.insertQuarter();
}
/// <summary>
/// 退回硬币
/// </summary>
public void ejectQuarter()
{
m_state.ejectQuarter();
}
/// <summary>
/// 转动曲柄,并自动发放糖果
/// </summary>
public void turnCrank()
{
m_state.turnCrank();
m_state.dispense();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StatePattern
{
class Program
{
static void Main(string[] args)
{
//开始放进10棵糖果到糖果机中
GumballMachine pGumballMachine = new GumballMachine(10);
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
pGumballMachine.insertQuarter();
pGumballMachine.turnCrank();
pGumballMachine.dispense();
Console.WriteLine(string.Format("剩余{0}颗糖果", pGumballMachine.GetCount()));
}
}
}
4、简单类图