程序设计中的主要设计模式通常分为三大类,共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)解释
模板方法模式是一种行为设计模式,它定义了一个算法的框架,并允许子类在不改变算法结构的情况下重新定义算法的某些步骤。模板方法模式的核心思想是将算法的通用部分放在父类中,而将可变的部分留给子类去实现。
模板方法模式的主要组成部分包括:
- 抽象类(Abstract Class):定义了一个模板方法,该方法包含了算法的骨架。模板方法通常会调用一些抽象方法或钩子方法,这些方法由子类实现。
- 具体类(Concrete Class):实现了抽象类中的抽象方法或钩子方法,从而具体化了算法的某些步骤。
模板方法模式的关键在于:父类控制算法的流程,子类实现具体的步骤。这种方式可以避免代码重复,并且使得算法的扩展更加灵活。
5.状态模式(State Pattern)解释
状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为。对象看起来像是修改了它的类。状态模式将对象的行为封装在不同的状态类中,使得对象在不同的状态下有不同的行为表现。
核心思想:
- 将对象的状态从对象中分离出来,封装到不同的状态类中。
- 对象的行为依赖于它的当前状态,并且可以在运行时根据状态改变行为。
- 状态模式通过将状态转移逻辑分散到不同的状态类中,避免了大量的条件判断语句。
主要角色:
- Context(上下文):维护一个当前状态对象的引用,并将与状态相关的操作委托给当前状态对象。
- State(状态接口):定义一个接口,用于封装与Context的特定状态相关的行为。
- 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.代码说明
IState 接口:定义了
Handle
方法,所有具体状态类都必须实现这个方法。Handle
方法用于处理上下文对象的状态变化。OnState 和 OffState 类:这两个类分别实现了
IState
接口,代表电灯的“开”和“关”状态。在Handle
方法中,它们会根据当前状态改变上下文对象的状态。Context 类:维护一个当前状态对象的引用,并通过
SetState
方法改变状态。Request
方法委托当前状态对象处理状态变化。Program 类:客户端代码,创建了一个
Context
对象,并模拟了电灯开关的操作。每次调用Request
方法,电灯的状态都会在“开”和“关”之间切换。
8.运行结果
电灯已经关闭,现在打开电灯。
电灯已经打开,现在关闭电灯。
电灯已经关闭,现在打开电灯。
9.总结
通过状态模式,我们将电灯的“开”和“关”状态分别封装到 OnState
和 OffState
类中,使得状态的变化更加清晰和易于扩展。如果需要添加新的状态,只需创建一个新的状态类并实现 IState
接口,而不需要修改现有的代码。这种设计模式非常适合处理对象状态复杂且状态转换频繁的场景。