设计模式(19)状态模式

模式介绍

状态模式旨在允许对象在其内部状态改变时改变其自身行为。

示例

我们以烤牛排为例,生熟程度分为:

  • Uncooked (not safe to eat)
  • Rare
  • Medium-Rare (mid-rare)
  • Medium
  • Medium-Well (mid-well)
  • Well done

简单来说就是从生到熟的几个档次。

抽象的状态类:

/// <summary>
/// The State abstract class
/// </summary>
abstract class Doneness
{
    protected Steak steak;
    protected double currentTemp;
    protected double lowerTemp;
    protected double upperTemp;
    protected bool canEat;

    public Steak Steak
    {
        get { return steak; }
        set { steak = value; }
    }

    public double CurrentTemp
    {
        get { return currentTemp; }
        set { currentTemp = value; }
    }

    public abstract void AddTemp(double temp);
    public abstract void RemoveTemp(double temp);
    public abstract void DonenessCheck();
}

具体的状态类:

/// <summary>
/// A Concrete State class.
/// </summary>
class Uncooked : Doneness
{
    public Uncooked(Doneness state)
    {
        currentTemp = state.CurrentTemp;
        steak = state.Steak;
        Initialize();
    }

    private void Initialize()
    {
        lowerTemp = 0;
        upperTemp = 130;
        canEat = false;
    }

    public override void AddTemp(double amount)
    {
        currentTemp += amount;
        DonenessCheck();
    }

    public override void RemoveTemp(double amount)
    {
        currentTemp -= amount;
        DonenessCheck();
    }

    public override void DonenessCheck()
    {
        if (currentTemp > upperTemp)
        {
            steak.State = new Rare(this);
        }
    }
}

/// <summary>
/// A 'ConcreteState' class.
/// </summary>
class Rare : Doneness
{
    public Rare(Doneness state) : this(state.CurrentTemp, state.Steak)
    {
    }

    public Rare(double currentTemp, Steak steak)
    {
        this.currentTemp = currentTemp;
        this.steak = steak;
        canEat = true; //We can now eat the steak
        Initialize();
    }

    private void Initialize()
    {
        lowerTemp = 130;
        upperTemp = 139.999999999999;
        canEat = true;
    }

    public override void AddTemp(double amount)
    {
        currentTemp += amount;
        DonenessCheck();
    }

    public override void RemoveTemp(double amount)
    {
        currentTemp -= amount;
        DonenessCheck();
    }

    public override void DonenessCheck()
    {
        if (currentTemp < lowerTemp)
        {
            steak.State = new Uncooked(this);
        }
        else if (currentTemp > upperTemp)
        {
            steak.State = new MediumRare(this);
        }
    }
}

/// <summary>
/// A Concrete State class
/// </summary>
class MediumRare : Doneness
{
    public MediumRare(Doneness state) : this(state.CurrentTemp, state.Steak)
    {
    }

    public MediumRare(double currentTemp, Steak steak)
    {
        this.currentTemp = currentTemp;
        this.steak = steak;
        canEat = true;
        Initialize();
    }

    private void Initialize()
    {
        lowerTemp = 140;
        upperTemp = 154.9999999999;
    }

    public override void AddTemp(double amount)
    {
        currentTemp += amount;
        DonenessCheck();
    }

    public override void RemoveTemp(double amount)
    {
        currentTemp -= amount;
        DonenessCheck();
    }

    public override void DonenessCheck()
    {
        if (currentTemp < 0.0)
        {
            steak.State = new Uncooked(this);
        }
        else if (currentTemp < lowerTemp)
        {
            steak.State = new Rare(this);
        }
        else if (currentTemp > upperTemp)
        {
            steak.State = new Medium(this);
        }
    }
}

/// <summary>
/// A Concrete State class
/// </summary>
class Medium : Doneness
{
    public Medium(Doneness state) : this(state.CurrentTemp, state.Steak)
    {
    }

    public Medium(double currentTemp, Steak steak)
    {
        this.currentTemp = currentTemp;
        this.steak = steak;
        canEat = true;
        Initialize();
    }

    private void Initialize()
    {
        lowerTemp = 155;
        upperTemp = 169.9999999999;
    }

    public override void AddTemp(double amount)
    {
        currentTemp += amount;
        DonenessCheck();
    }

    public override void RemoveTemp(double amount)
    {
        currentTemp -= amount;
        DonenessCheck();
    }

    public override void DonenessCheck()
    {
        if (currentTemp < 130)
        {
            steak.State = new Uncooked(this);
        }
        else if (currentTemp < lowerTemp)
        {
            steak.State = new MediumRare(this);
        }
        else if (currentTemp > upperTemp)
        {
            steak.State = new WellDone(this);
        }
    }
}

/// <summary>
/// A Concrete State class
/// </summary>
class WellDone : Doneness //aka Ruined
{
    public WellDone(Doneness state) : this(state.CurrentTemp, state.Steak)
    {
    }

    public WellDone(double currentTemp, Steak steak)
    {
        this.currentTemp = currentTemp;
        this.steak = steak;
        canEat = true;
        Initialize();
    }

    private void Initialize()
    {
        lowerTemp = 170;
        upperTemp = 230;
    }

    public override void AddTemp(double amount)
    {
        currentTemp += amount;
        DonenessCheck();
    }

    public override void RemoveTemp(double amount)
    {
        currentTemp -= amount;
        DonenessCheck();
    }

    public override void DonenessCheck()
    {
        if (currentTemp < 0)
        {
            steak.State = new Uncooked(this);
        }
        else if (currentTemp < lowerTemp)
        {
            steak.State = new Medium(this);
        }
    }
}

上下文类-牛排:

/// <summary>
/// The Context class
/// </summary>
class Steak
{
    private Doneness _state;
    private string _beefCut;

    public Steak(string beefCut)
    {
        _cook = beefCut;
        _state = new Rare(0.0, this);
    }

    public double CurrentTemp
    {
        get { return _state.CurrentTemp; }
    }

    public Doneness State
    {
        get { return _state; }
        set { _state = value; }
    }

    public void AddTemp(double amount)
    {
        _state.AddTemp(amount);
        Console.WriteLine("Increased temperature by {0} degrees.", amount);
        Console.WriteLine(" Current temp is {0}", CurrentTemp);
        Console.WriteLine(" Status is {0}", State.GetType().Name);
        Console.WriteLine("");
    }

    public void RemoveTemp(double amount)
    {
        _state.RemoveTemp(amount);
        Console.WriteLine("Decreased temperature by {0} degrees.", amount);
        Console.WriteLine(" Current temp is {0}", CurrentTemp);
        Console.WriteLine(" Status is {0}", State.GetType().Name);
        Console.WriteLine("");
    }
}

客户端调用:

static void Main(string[] args)
{
    //Let's cook a steak!
    Steak account = new Steak("T-Bone");

    // Apply temperature changes
    account.AddTemp(120);
    account.AddTemp(15);
    account.AddTemp(15);
    account.RemoveTemp(10); //Yes I know cooking doesn't work this way, bear with me.
    account.RemoveTemp(15);
    account.AddTemp(20);
    account.AddTemp(20);
    account.AddTemp(20);

    Console.ReadKey();
}

总结

状态模式允许对象的行为随着其内部状态的改变而改变,并且它通过使对象的状态与对象本身分开来完成这一任务。
因此,状态可以为对象实现它们自己的行为,并且对象可以对其内部状态改变作出“反应”。

源代码

https://github.com/exceptionnotfound/DesignPatterns/tree/master/State

原文

https://www.exceptionnotfound.net/state-the-daily-design-pattern/

原文地址:https://www.cnblogs.com/talentzemin/p/9956461.html