设计模式笔记
23 种设计模式
创建型模式(Creational Patterns)
1. 单例模式(Singleton)
定义:保证一个类只有一个实例,并提供一个全局访问点。
通俗理解:就像全国只有一个身份证号码,每个人都唯一,不能重复。
适用场景:只需要一个对象的场合,如配置管理器、日志对象。
// 单例模式示例
public sealed class Singleton
{
private static readonly Singleton _instance = new Singleton();
public string Config { get; set; } = "默认配置";
private Singleton() { }
public static Singleton Instance => _instance;
}
// 调用示例
var obj1 = Singleton.Instance;
var obj2 = Singleton.Instance;
obj1.Config = "新配置";
Console.WriteLine(obj2.Config); // 输出:新配置
2. 工厂方法模式(Factory Method)
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
通俗理解:就像开工厂生产产品,不同工厂生产不同产品。
适用场景:当一个类不知道它所需要创建的对象的类时。
// 工厂方法模式示例
interface IProduct
{
void Show();
}
class ProductA : IProduct
{
public void Show() => Console.WriteLine("我是产品A");
}
class ProductB : IProduct
{
public void Show() => Console.WriteLine("我是产品B");
}
abstract class Creator
{
public abstract IProduct FactoryMethod();
}
class CreatorA : Creator
{
public override IProduct FactoryMethod() => new ProductA();
}
class CreatorB : Creator
{
public override IProduct FactoryMethod() => new ProductB();
}
// 调用示例
Creator factory = new CreatorA();
IProduct product = factory.FactoryMethod();
product.Show(); // 输出:我是产品A
factory = new CreatorB();
product = factory.FactoryMethod();
product.Show(); // 输出:我是产品B
3. 抽象工厂模式(Abstract Factory)
定义:提供一个创建一系列相关或相互依赖对象的接口。
通俗理解:像宜家家居套餐,一次性买齐风格统一的家具。
适用场景:需要创建一系列相关产品对象时。
// 抽象工厂模式示例
interface IButton
{
void Paint();
}
interface ITextBox
{
void Show();
}
class WinButton : IButton
{
public void Paint() => Console.WriteLine("Windows按钮");
}
class MacButton : IButton
{
public void Paint() => Console.WriteLine("Mac按钮");
}
class WinTextBox : ITextBox
{
public void Show() => Console.WriteLine("Windows文本框");
}
class MacTextBox : ITextBox
{
public void Show() => Console.WriteLine("Mac文本框");
}
interface IGUIFactory
{
IButton CreateButton();
ITextBox CreateTextBox();
}
class WinFactory : IGUIFactory
{
public IButton CreateButton() => new WinButton();
public ITextBox CreateTextBox() => new WinTextBox();
}
class MacFactory : IGUIFactory
{
public IButton CreateButton() => new MacButton();
public ITextBox CreateTextBox() => new MacTextBox();
}
// 调用示例
IGUIFactory factory = new WinFactory();
factory.CreateButton().Paint(); // 输出:Windows按钮
factory.CreateTextBox().Show(); // 输出:Windows文本框
factory = new MacFactory();
factory.CreateButton().Paint(); // 输出:Mac按钮
factory.CreateTextBox().Show(); // 输出:Mac文本框
4. 建造者模式(Builder)
定义:将一个复杂对象的构建与表示分离,使同样的构建过程可以创建不同的表示。
通俗理解:像搭积木,先搭框架再装饰细节。
适用场景:需要构建复杂对象时。
// 建造者模式示例
class Meal
{
public List<string> Parts = new();
public void Show() => Console.WriteLine(string.Join(", ", Parts));
}
interface IMealBuilder
{
void BuildMain();
void BuildDrink();
Meal GetMeal();
}
class ChineseMealBuilder : IMealBuilder
{
private Meal _meal = new Meal();
public void BuildMain() => _meal.Parts.Add("米饭");
public void BuildDrink() => _meal.Parts.Add("豆浆");
public Meal GetMeal() => _meal;
}
class WesternMealBuilder : IMealBuilder
{
private Meal _meal = new Meal();
public void BuildMain() => _meal.Parts.Add("牛排");
public void BuildDrink() => _meal.Parts.Add("红酒");
public Meal GetMeal() => _meal;
}
class Waiter
{
public void Construct(IMealBuilder builder)
{
builder.BuildMain();
builder.BuildDrink();
}
}
// 调用示例
Waiter waiter = new Waiter();
IMealBuilder builder = new ChineseMealBuilder();
waiter.Construct(builder);
builder.GetMeal().Show(); // 输出:米饭, 豆浆
builder = new WesternMealBuilder();
waiter.Construct(builder);
builder.GetMeal().Show(); // 输出:牛排, 红酒
5. 原型模式(Prototype)
定义:通过复制已有实例创建新对象。
通俗理解:像复印文件,快速复制出一份一模一样的。
适用场景:需要大量相同或相似对象时。
// 原型模式示例
class Resume : ICloneable
{
public string Name;
public Resume(string name) { Name = name; }
public object Clone() => new Resume(Name);
}
// 调用示例
Resume r1 = new Resume("小明");
Resume r2 = (Resume)r1.Clone();
Console.WriteLine(r2.Name); // 输出:小明
结构型模式(Structural Patterns)
6. 适配器模式(Adapter)
定义:将一个接口转换成客户端期望的另一个接口。
通俗理解:像插头转换器,让不同国家的插头都能用。
适用场景:系统需要使用现有的类,但接口不兼容时。
// 适配器模式示例
interface ITarget
{
void Request();
}
class Adaptee
{
public void SpecificRequest() => Console.WriteLine("特殊请求");
}
class Adapter : ITarget
{
private Adaptee _adaptee = new Adaptee();
public void Request() => _adaptee.SpecificRequest();
}
// 调用示例
ITarget target = new Adapter();
target.Request(); // 输出:特殊请求
7. 桥接模式(Bridge)
定义:将抽象部分与其实现部分分离,使它们可以独立变化。
通俗理解:像遥控器和电视,遥控器控制不同品牌的电视。
适用场景:抽象和实现都需要扩展时。
// 桥接模式示例
interface ITV
{
void Play();
}
class SonyTV : ITV
{
public void Play() => Console.WriteLine("播放Sony电视");
}
class TCLTV : ITV
{
public void Play() => Console.WriteLine("播放TCL电视");
}
abstract class RemoteControl
{
protected ITV tv;
public RemoteControl(ITV tv) { this.tv = tv; }
public abstract void Operate();
}
class ConcreteRemote : RemoteControl
{
public ConcreteRemote(ITV tv) : base(tv) { }
public override void Operate() => tv.Play();
}
// 调用示例
RemoteControl remote = new ConcreteRemote(new SonyTV());
remote.Operate(); // 输出:播放Sony电视
remote = new ConcreteRemote(new TCLTV());
remote.Operate(); // 输出:播放TCL电视
8. 组合模式(Composite)
定义:将对象组合成树形结构以表示"部分-整体"层次结构。
通俗理解:像公司组织架构,部门下有小组,小组下有员工。
适用场景:需要表示对象的部分-整体层次结构时。
// 组合模式示例
abstract class Company
{
public string Name;
public Company(string name) { Name = name; }
public abstract void Display(int depth);
}
class Department : Company
{
public Department(string name) : base(name) { }
public override void Display(int depth) => Console.WriteLine(new string('-', depth) + Name);
}
class CompositeCompany : Company
{
private List<Company> children = new();
public CompositeCompany(string name) : base(name) { }
public void Add(Company c) => children.Add(c);
public override void Display(int depth)
{
Console.WriteLine(new string('-', depth) + Name);
foreach (var c in children) c.Display(depth + 2);
}
}
// 调用示例
CompositeCompany root = new CompositeCompany("总公司");
root.Add(new Department("人事部"));
CompositeCompany branch = new CompositeCompany("分公司");
branch.Add(new Department("财务部"));
root.Add(branch);
root.Display(1);
9. 装饰器模式(Decorator)
定义:动态地给对象添加职责。
通俗理解:像给手机加壳、贴膜,功能增强但本体不变。
适用场景:需要动态扩展对象功能时。
// 装饰器模式示例
interface ICoffee
{
string GetDescription();
}
class SimpleCoffee : ICoffee
{
public string GetDescription() => "黑咖啡";
}
class MilkDecorator : ICoffee
{
private ICoffee _coffee;
public MilkDecorator(ICoffee coffee) { _coffee = coffee; }
public string GetDescription() => _coffee.GetDescription() + "+牛奶";
}
class SugarDecorator : ICoffee
{
private ICoffee _coffee;
public SugarDecorator(ICoffee coffee) { _coffee = coffee; }
public string GetDescription() => _coffee.GetDescription() + "+糖";
}
// 调用示例
ICoffee coffee = new SimpleCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
Console.WriteLine(coffee.GetDescription()); // 输出:黑咖啡+牛奶+糖
10. 外观模式(Facade)
定义:为子系统中的一组接口提供统一的接口。
通俗理解:像万能遥控器,一键控制多个家电。
适用场景:为复杂子系统提供简单接口时。
// 外观模式示例
class Light
{
public void On() => Console.WriteLine("开灯");
}
class TV
{
public void On() => Console.WriteLine("开电视");
}
class Facade
{
private Light _light = new Light();
private TV _tv = new TV();
public void MovieMode()
{
_light.On();
_tv.On();
}
}
// 调用示例
Facade facade = new Facade();
facade.MovieMode(); // 输出:开灯\n开电视
11. 享元模式(Flyweight)
定义:运用共享技术有效地支持大量细粒度对象。
通俗理解:像汉字字形库,常用字只存一份,节省内存。
适用场景:大量对象中有可共享部分时。
// 享元模式示例
class ChessPiece
{
public string Color;
public ChessPiece(string color) { Color = color; }
public void Display(int x, int y) => Console.WriteLine($"{Color}棋子在({x},{y})");
}
class ChessFactory
{
private Dictionary<string, ChessPiece> _pool = new();
public ChessPiece GetPiece(string color)
{
if (!_pool.ContainsKey(color)) _pool[color] = new ChessPiece(color);
return _pool[color];
}
}
// 调用示例
ChessFactory factory = new ChessFactory();
ChessPiece black1 = factory.GetPiece("黑");
ChessPiece black2 = factory.GetPiece("黑");
Console.WriteLine(object.ReferenceEquals(black1, black2)); // 输出:True
black1.Display(1, 2);
12. 代理模式(Proxy)
定义:为其他对象提供一个代理以控制对这个对象的访问。
通俗理解:像明星经纪人,粉丝不能直接联系明星,要通过经纪人。
适用场景:需要为对象提供访问控制时。
// 代理模式示例
interface IStar
{
void Meet();
}
class RealStar : IStar
{
public void Meet() => Console.WriteLine("明星见粉丝");
}
class StarProxy : IStar
{
private RealStar _star = new RealStar();
public void Meet()
{
Console.WriteLine("经纪人安排见面");
_star.Meet();
}
}
// 调用示例
IStar star = new StarProxy();
star.Meet(); // 输出:经纪人安排见面\n明星见粉丝
行为型模式(Behavioral Patterns)
13. 责任链模式(Chain of Responsibility)
定义:使多个对象都有机会处理请求,避免请求的发送者和接收者耦合。
通俗理解:像公司请假流程,先找组长批,组长批不了再找经理。
适用场景:有多个对象可以处理同一请求时。
// 责任链模式示例
abstract class Approver
{
protected Approver Next;
public void SetNext(Approver next) { Next = next; }
public abstract void Handle(int days);
}
class Leader : Approver
{
public override void Handle(int days)
{
if (days <= 1) Console.WriteLine("组长批准");
else if (Next != null) Next.Handle(days);
}
}
class Manager : Approver
{
public override void Handle(int days)
{
if (days <= 3) Console.WriteLine("经理批准");
else if (Next != null) Next.Handle(days);
}
}
// 调用示例
Approver leader = new Leader();
Approver manager = new Manager();
leader.SetNext(manager);
leader.Handle(1); // 输出:组长批准
leader.Handle(2); // 输出:经理批准
14. 命令模式(Command)
定义:将请求封装为对象,从而让你使用不同的请求、队列或日志参数化其他对象。
通俗理解:像点外卖,点单(命令)后,骑手(执行者)去完成。
适用场景:需要将操作请求、撤销、排队等功能封装时。
// 命令模式示例
interface ICommand
{
void Execute();
}
class Light
{
public void On() => Console.WriteLine("开灯");
}
class LightOnCommand : ICommand
{
private Light _light;
public LightOnCommand(Light light) { _light = light; }
public void Execute() => _light.On();
}
class Remote
{
private ICommand _command;
public void SetCommand(ICommand command) { _command = command; }
public void PressButton() { _command.Execute(); }
}
// 调用示例
Light light = new Light();
ICommand command = new LightOnCommand(light);
Remote remote = new Remote();
remote.SetCommand(command);
remote.PressButton(); // 输出:开灯
15. 解释器模式(Interpreter)
定义:给定一种语言,定义它的文法的一种表示,并定义一个解释器。
通俗理解:像计算器,输入表达式自动计算结果。
适用场景:需要解释执行某种语法规则时。
// 解释器模式示例
interface IExpression
{
int Interpret();
}
class Number : IExpression
{
private int _value;
public Number(int value) { _value = value; }
public int Interpret() => _value;
}
class Add : IExpression
{
private IExpression _left, _right;
public Add(IExpression left, IExpression right) { _left = left; _right = right; }
public int Interpret() => _left.Interpret() + _right.Interpret();
}
// 调用示例
IExpression expr = new Add(new Number(1), new Number(2));
Console.WriteLine(expr.Interpret()); // 输出:3
16. 迭代器模式(Iterator)
定义:提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露该对象的内部表示。
通俗理解:像翻书,一页一页往下看。
适用场景:需要遍历集合对象时。
// 迭代器模式示例
class MyCollection
{
private List<string> _items = new() { "A", "B" };
public IEnumerator<string> GetEnumerator() => _items.GetEnumerator();
}
// 调用示例
MyCollection collection = new MyCollection();
foreach (var item in collection.GetEnumerator())
Console.WriteLine(item); // 输出:A\nB
17. 中介者模式(Mediator)
定义:用一个中介对象封装一系列对象之间的交互。
通俗理解:像微信群,大家不直接私聊,而是通过群(中介)沟通。
适用场景:对象之间存在复杂引用关系时。
// 中介者模式示例
class ChatRoom
{
public static void ShowMessage(string user, string message)
{
Console.WriteLine($"{user}说: {message}");
}
}
class User
{
public string Name;
public User(string name) { Name = name; }
public void Send(string message)
{
ChatRoom.ShowMessage(Name, message);
}
}
// 调用示例
User tom = new User("Tom");
User jerry = new User("Jerry");
tom.Send("你好"); // 输出:Tom说: 你好
jerry.Send("Hi"); // 输出:Jerry说: Hi
18. 备忘录模式(Memento)
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
通俗理解:像游戏存档,随时保存和恢复进度。
适用场景:需要保存和恢复对象历史状态时。
// 备忘录模式示例
class Memento
{
public string State;
public Memento(string s) { State = s; }
}
class Originator
{
public string State;
public Memento Save() => new Memento(State);
public void Restore(Memento m) { State = m.State; }
}
// 调用示例
Originator originator = new Originator();
originator.State = "状态1";
Memento memento = originator.Save();
originator.State = "状态2";
originator.Restore(memento);
Console.WriteLine(originator.State); // 输出:状态1
19. 观察者模式(Observer)
定义:对象间一对多依赖,一个对象状态变化,所有依赖者都会收到通知。
通俗理解:像微信公众号,推送新消息所有粉丝都能收到。
适用场景:一个对象变化需要通知其他对象时。
// 观察者模式示例
interface IObserver
{
void Update(string msg);
}
class Subscriber : IObserver
{
public void Update(string msg) => Console.WriteLine($"收到消息: {msg}");
}
class Publisher
{
private List<IObserver> observers = new();
public void Add(IObserver o) => observers.Add(o);
public void Notify(string msg)
{
foreach (var o in observers) o.Update(msg);
}
}
// 调用示例
Publisher pub = new Publisher();
IObserver sub = new Subscriber();
pub.Add(sub);
pub.Notify("新内容"); // 输出:收到消息: 新内容
20. 状态模式(State)
定义:允许对象在内部状态改变时改变它的行为。
通俗理解:像红绿灯,灯变色后交通规则也变。
适用场景:对象行为依赖于状态变化时。
// 状态模式示例
interface IState
{
void Handle();
}
class RedState : IState
{
public void Handle() => Console.WriteLine("红灯停");
}
class GreenState : IState
{
public void Handle() => Console.WriteLine("绿灯行");
}
class Context
{
public IState State;
public void Request() => State.Handle();
}
// 调用示例
Context context = new Context();
context.State = new RedState();
context.Request(); // 输出:红灯停
context.State = new GreenState();
context.Request(); // 输出:绿灯行
21. 策略模式(Strategy)
定义:定义一系列算法,把它们一个个封装起来,并且使它们可以互换。
通俗理解:像出行方式,打车、骑车、步行,随时切换。
适用场景:需要在多种算法中选择时。
// 策略模式示例
interface IStrategy
{
int Calculate(int a, int b);
}
class AddStrategy : IStrategy
{
public int Calculate(int a, int b) => a + b;
}
class SubStrategy : IStrategy
{
public int Calculate(int a, int b) => a - b;
}
class Calculator
{
public IStrategy Strategy;
public int Execute(int a, int b) => Strategy.Calculate(a, b);
}
// 调用示例
Calculator calc = new Calculator();
calc.Strategy = new AddStrategy();
Console.WriteLine(calc.Execute(1, 2)); // 输出:3
calc.Strategy = new SubStrategy();
Console.WriteLine(calc.Execute(5, 3)); // 输出:2
22. 模板方法模式(Template Method)
定义:定义一个操作中的算法骨架,将一些步骤延迟到子类实现。
通俗理解:像做饭流程,先洗菜再炒菜,具体怎么洗炒由厨师决定。
适用场景:多个子类有相同方法结构但实现不同。
// 模板方法模式示例
abstract class Cook
{
public void MakeDish()
{
Wash();
CookMain();
Serve();
}
protected abstract void CookMain();
private void Wash() => Console.WriteLine("洗菜");
private void Serve() => Console.WriteLine("上菜");
}
class FriedRice : Cook
{
protected override void CookMain() => Console.WriteLine("炒饭");
}
// 调用示例
Cook cook = new FriedRice();
cook.MakeDish(); // 输出:洗菜\n炒饭\n上菜
23. 访问者模式(Visitor)
定义:表示一个作用于某对象结构中的各元素的操作。
通俗理解:像快递员上门收件,不同快递员对包裹有不同处理方式。
适用场景:需要对一组对象进行多种操作时。
// 访问者模式示例
interface IVisitor
{
void Visit(Book book);
}
class Book
{
public string Name;
public Book(string name) { Name = name; }
public void Accept(IVisitor visitor) => visitor.Visit(this);
}
class PriceVisitor : IVisitor
{
public void Visit(Book book) => Console.WriteLine($"{book.Name}定价100元");
}
// 调用示例
Book book = new Book("设计模式");
IVisitor visitor = new PriceVisitor();
book.Accept(visitor); // 输出:设计模式定价100元
总结:设计模式对比表
模式名称 | 实用度 | 复杂度 | 优点 | 缺点 | 常见场景 | 现实类比 |
---|---|---|---|---|---|---|
单例 | ★★★★★ | ★ | 全局唯一、节省资源 | 线程安全需注意 | 配置、日志 | 身份证号 |
工厂方法 | ★★★★☆ | ★★ | 解耦创建与使用 | 类数量增多 | 对象创建灵活 | 汽车工厂 |
抽象工厂 | ★★★★☆ | ★★★ | 产品族一致、易扩展 | 新增产品族难 | 一系列相关产品 | 家具套餐 |
建造者 | ★★★☆☆ | ★★★ | 分步构建、灵活 | 结构复杂 | 复杂对象组装 | 盖房子 |
原型模式 | ★★★☆☆ | ★★ | 快速复制、无需new | 深拷贝复杂 | 批量相似对象 | 复印文件 |
适配器 | ★★★★☆ | ★★ | 兼容性强、复用旧代码 | 可能影响性能 | 接口转换 | 插头转换器 |
桥接模式 | ★★★☆☆ | ★★★ | 抽象与实现分离 | 设计复杂 | 多维度扩展 | 遥控器与电视 |
组合模式 | ★★★★☆ | ★★★ | 层级结构清晰 | 管理复杂 | 树形结构 | 公司组织架构 |
装饰器 | ★★★★☆ | ★★★ | 动态扩展功能 | 多层装饰难维护 | 功能增强 | 手机壳 |
外观模式 | ★★★★☆ | ★ | 简化接口、降低耦合 | 不易细粒度控制 | 子系统封装 | 万能遥控器 |
享元模式 | ★★★☆☆ | ★★★★ | 节省内存 | 逻辑复杂 | 大量细粒度对象 | 汉字字形库 |
代理模式 | ★★★★☆ | ★★ | 控制访问、增强功能 | 增加间接层 | 远程/安全控制 | 经纪人 |
责任链 | ★★★★☆ | ★★★ | 请求灵活传递 | 调试困难 | 审批流、日志处理 | 请假流程 |
命令模式 | ★★★☆☆ | ★★★ | 请求封装、可撤销 | 类增多 | 操作记录、事务 | 点外卖 |
解释器 | ★★☆☆☆ | ★★★★ | 易扩展语法 | 效率低 | 表达式计算 | 计算器 |
迭代器 | ★★★★☆ | ★ | 统一遍历接口 | 仅适合线性结构 | 集合遍历 | 翻书 |
中介者 | ★★★☆☆ | ★★★ | 降低耦合 | 中介者复杂 | 多对象交互 | 微信群 |
备忘录 | ★★★☆☆ | ★★ | 状态恢复 | 占用资源 | 撤销、恢复 | 游戏存档 |
观察者 | ★★★★★ | ★★ | 解耦通知 | 可能有性能问题 | 事件通知 | 微信公众号 |
状态模式 | ★★★☆☆ | ★★★ | 状态切换灵活 | 状态类增多 | 状态驱动行为 | 红绿灯 |
策略模式 | ★★★★☆ | ★★ | 算法可切换 | 客户端需知策略 | 多算法选择 | 出行方式 |
模板方法 | ★★★★☆ | ★★ | 复用流程、易扩展 | 不灵活 | 固定流程 | 做饭流程 |
访问者 | ★★☆☆☆ | ★★★★ | 新操作易扩展 | 结构变动难 | 多操作对象结构 | 快递员收件 |
注:实用度和复杂度为主观评价,仅供参考。