设计模式(15)----- 状态模式

状态模式(State)

关键词:状态决定行为

问题:

对象状态的改变,从而带来行为上的变化。

意图:

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

适用性:

  1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  2. 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
  3. 这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。
  4. State模式将每一个条件分支放入一个独立的类中,这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一个对象可以不依赖于其他对象而独立变化。

优点:

  1. 封装了转换规则。
  2. 枚举可能的状态,在枚举状态之前需要确定状态种类。
  3. 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  4. 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
  5. 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:

  1. 状态模式的使用必然会增加系统类和对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  3. 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

实现类图
在这里插入图片描述
所有状态的父类 State

/// <summary>
/// 状态基类
/// </summary>
public abstract class State
{   //状态名称
    protected string strStatename;
    //状态行为
    abstract public void Pour();
}

状态枚举 判断都有那些状态

/// <summary>
/// 状态枚举
/// </summary>
public enum StateSetting
{
    Closed,//关闭状态
    Opened,//开口状态
}

开口状态 子类 OpenedState

using System;
/// <summary>
/// 开口状态
/// </summary>
public class OpenedState : State
{   //初始化
    public OpenedState()
    {
        strStatename = "Opened";
    }
    public override void Pour()
    {   //重写方法   实现开口状态方法
        Console.WriteLine("可以倒出水来,当前状态是开口状态");
    }
}

关闭状态 子类 ClosedState

using System;
/// <summary>
/// 关闭状态
/// </summary>
public class ClosedState : State
{   //初始化
    public ClosedState()
    {
        strStatename = "Closed";
    }
    public override void Pour()
    {   //重写方法  实现关闭状态下的行为
        Console.WriteLine("不能倒出水,当前状态是关闭状态");
    }
}

状态机

using System;
/// <summary>
/// 状态机
/// </summary>
public class 瓶子_状态机
{
    //静态创建对象  适合功能比较少
    //ClosedState closedState = new ClosedState();
    //OpenedState openState = new OpenedState();
    
    //定义当前状态
    private State CurrentState;
    //初始化当前状态为关闭状态
    public 瓶子_状态机()
    {
        CurrentState = new ClosedState();
    }
    /// <summary>
    /// 更新状态
    /// </summary>
    /// <param name="newState">要更新的状态</param>
    public void SetState(StateSetting newState)
    {
        // 动态创建状态对象 - 反射
        //定义状态集合  反射技术  把每个状态放到  状态集合中
        //取得状态类名称
        string allName = newState + "State";
        //通过类名  得到Type对象
        Type typeObj = Type.GetType(allName);
        //通过Type对象  创建指定类型的实例  给当前状态
        CurrentState = (State)Activator.CreateInstance(typeObj);
    }
    //调用当前状态的Pour方法
    public void Pour()
    {
        CurrentState.Pour();
    }
}

测试

using System;

class Program
{
    static void Main(string[] args)
    {
        //定义状态机
        瓶子_状态机 p = new 瓶子_状态机();
        //判断当前状态是否可以倒出水来
        p.Pour();
        //更改状态  为开口状态
        p.SetState(StateSetting.Opened);
        //测试
        p.Pour();
        //更改状态  为关闭状态
        p.SetState(StateSetting.Closed);
        //测试
        p.Pour();

        Console.Read();
    }
}

输出样例
在这里插入图片描述
设计模式------首页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值