23种设计模式之《状态模式(State)》在c#中的应用及理解

程序设计中的主要设计模式通常分为三大类,共23种:

1. 创建型模式(Creational Patterns)

  • 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。

  • 工厂方法模式(Factory Method):定义创建对象的接口,由子类决定实例化哪个类。

  • 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或依赖对象的接口,而无需指定具体类。

  • 建造者模式(Builder):将一个复杂对象的构建与其表示分离,使同样的构建过程可以创建不同的表示。

  • 原型模式(Prototype):通过复制现有对象来创建新对象。

2. 结构型模式(Structural Patterns)

  • 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。

  • 桥接模式(Bridge):将抽象部分与实现部分分离,使它们可以独立变化。

  • 组合模式(Composite):将对象组合成树形结构以表示"部分-整体"的层次结构。

  • 装饰器模式(Decorator):动态地给对象添加职责,相比生成子类更为灵活。

  • 外观模式(Facade):为子系统中的一组接口提供一个统一的接口。

  • 享元模式(Flyweight):通过共享技术有效地支持大量细粒度对象。

  • 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。

3. 行为型模式(Behavioral Patterns)

  • 责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者与接收者耦合。

  • 命令模式(Command):将请求封装为对象,使你可以用不同的请求对客户进行参数化。

  • 解释器模式(Interpreter):给定一个语言,定义其文法的一种表示,并定义一个解释器。

  • 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示。

  • 中介者模式(Mediator):定义一个中介对象来封装一系列对象之间的交互。

  • 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

  • 观察者模式(Observer):定义对象间的一对多依赖关系,当一个对象改变状态时,所有依赖者都会收到通知并自动更新。

  • 状态模式(State):允许对象在其内部状态改变时改变其行为。

  • 策略模式(Strategy):定义一系列算法,将它们封装起来,并使它们可以互相替换。

  • 模板方法模式(Template Method):定义一个操作中的算法骨架,将一些步骤延迟到子类中。

  • 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

4.模板方法模式(Template Method Pattern)解释

模板方法模式是一种行为设计模式,它定义了一个算法的框架,并允许子类在不改变算法结构的情况下重新定义算法的某些步骤。模板方法模式的核心思想是将算法的通用部分放在父类中,而将可变的部分留给子类去实现。

模板方法模式的主要组成部分包括:

  1. 抽象类(Abstract Class)​:定义了一个模板方法,该方法包含了算法的骨架。模板方法通常会调用一些抽象方法或钩子方法,这些方法由子类实现。
  2. 具体类(Concrete Class)​:实现了抽象类中的抽象方法或钩子方法,从而具体化了算法的某些步骤。

模板方法模式的关键在于:​父类控制算法的流程,子类实现具体的步骤。这种方式可以避免代码重复,并且使得算法的扩展更加灵活。

5.状态模式(State Pattern)解释

状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为。对象看起来像是修改了它的类。状态模式将对象的行为封装在不同的状态类中,使得对象在不同的状态下有不同的行为表现。

核心思想

  • 将对象的状态从对象中分离出来,封装到不同的状态类中。
  • 对象的行为依赖于它的当前状态,并且可以在运行时根据状态改变行为。
  • 状态模式通过将状态转移逻辑分散到不同的状态类中,避免了大量的条件判断语句。

主要角色

  1. Context(上下文)​:维护一个当前状态对象的引用,并将与状态相关的操作委托给当前状态对象。
  2. State(状态接口)​:定义一个接口,用于封装与Context的特定状态相关的行为。
  3. ConcreteState(具体状态类)​:实现State接口,定义与Context的特定状态相关的行为。

6.C# 状态模式演示代码

下面是一个简单的状态模式示例,模拟一个电灯开关的状态变化。

复制代码

csharp

复制代码
using System;

// 状态接口
interface IState
{
    void Handle(Context context);
}

// 具体状态类:开状态
class OnState : IState
{
    public void Handle(Context context)
    {
        Console.WriteLine("电灯已经打开,现在关闭电灯。");
        context.SetState(new OffState());
    }
}

// 具体状态类:关状态
class OffState : IState
{
    public void Handle(Context context)
    {
        Console.WriteLine("电灯已经关闭,现在打开电灯。");
        context.SetState(new OnState());
    }
}

// 上下文类
class Context
{
    private IState _currentState;

    public Context(IState state)
    {
        _currentState = state;
    }

    public void SetState(IState state)
    {
        _currentState = state;
    }

    public void Request()
    {
        _currentState.Handle(this);
    }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        // 初始状态为关
        Context context = new Context(new OffState());

        // 模拟电灯开关操作
        context.Request(); // 打开电灯
        context.Request(); // 关闭电灯
        context.Request(); // 打开电灯
    }
}

7.代码说明

  1. IState 接口 :定义了 Handle 方法,所有具体状态类都必须实现这个方法。Handle 方法用于处理上下文对象的状态变化。

  2. OnState 和 OffState 类 :这两个类分别实现了 IState 接口,代表电灯的"开"和"关"状态。在 Handle 方法中,它们会根据当前状态改变上下文对象的状态。

  3. Context 类 :维护一个当前状态对象的引用,并通过 SetState 方法改变状态。Request 方法委托当前状态对象处理状态变化。

  4. Program 类 :客户端代码,创建了一个 Context 对象,并模拟了电灯开关的操作。每次调用 Request 方法,电灯的状态都会在"开"和"关"之间切换。

8.运行结果

复制代码
电灯已经关闭,现在打开电灯。
电灯已经打开,现在关闭电灯。
电灯已经关闭,现在打开电灯。

9.总结

通过状态模式,我们将电灯的"开"和"关"状态分别封装到 OnStateOffState 类中,使得状态的变化更加清晰和易于扩展。如果需要添加新的状态,只需创建一个新的状态类并实现 IState 接口,而不需要修改现有的代码。这种设计模式非常适合处理对象状态复杂且状态转换频繁的场景。

相关推荐
触底反弹3 小时前
🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
人工智能·设计模式·面试
杨充1 天前
10.可测试性实战设计
设计模式·开源·代码规范
杨充1 天前
9.重构十二式的实战
设计模式·开源·代码规范
杨充1 天前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 天前
2.面向对象的特性
设计模式
杨充1 天前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 天前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法