23种设计模式解析--行为型

发布于:2025-08-10 ⋅ 阅读:(20) ⋅ 点赞:(0)
行为型模式(协作的艺术)
  1. 观察者模式

观察者模式详解

模式定义

观察者模式(Observer Pattern)是一种行为设计模式,用于建立对象间一对多的依赖关系。当一个对象(Subject)状态变化时,所有依赖它的对象(Observers)会自动收到通知并更新。该模式解耦了主题与观察者,遵循开闭原则(对扩展开放,对修改关闭)。

核心组件
  1. Subject (主题)
    • 维护观察者列表(添加/删除方法)
    • 提供状态更新通知方法(NotifyObservers
  2. Observer (观察者接口)
    • 定义更新接口(如Update()
  3. ConcreteObserver (具体观察者)
    • 实现更新逻辑,与主题状态同步
  4. ConcreteSubject (具体主题)
    • 存储具体状态,状态变更时触发通知

C# 实现示例

// 主题接口
public interface ISubject {
    void RegisterObserver(IObserver o);
    void RemoveObserver(IObserver o);
    void NotifyObservers();
}

// 观察者接口
public interface IObserver {
    void Update(string message);
}

// 具体主题(新闻发布中心)
public class NewsAgency : ISubject {
    private List<IObserver> _observers = new List<IObserver>();
    private string _latestNews;

    public void RegisterObserver(IObserver o) => _observers.Add(o);
    public void RemoveObserver(IObserver o) => _observers.Remove(o);
    
    public void NotifyObservers() {
        foreach (var observer in _observers) {
            observer.Update(_latestNews);
        }
    }

    public void PublishNews(string news) {
        _latestNews = news;
        NotifyObservers(); // 状态变更时自动通知
    }
}

// 具体观察者(新闻订阅用户)
public class NewsSubscriber : IObserver {
    private string _name;
    public NewsSubscriber(string name) => _name = name;
    
    public void Update(string news) {
        Console.WriteLine($"{_name} received news: {news}");
    }
}

// 使用
var agency = new NewsAgency();
var user1 = new NewsSubscriber("User1");
var user2 = new NewsSubscriber("User2");

agency.RegisterObserver(user1);
agency.RegisterObserver(user2);
agency.PublishNews("Breaking: New AI Model Released!");

Java 实现示例

import java.util.*;

// 主题接口
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

// 观察者接口
interface Observer {
    void update(String message);
}

// 具体主题(股票交易所)
class StockExchange implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private double stockPrice;

    public void registerObserver(Observer o) { observers.add(o); }
    public void removeObserver(Observer o) { observers.remove(o); }
    
    public void notifyObservers() {
        for (Observer o : observers) {
            o.update("Price updated: " + stockPrice);
        }
    }

    public void setStockPrice(double price) {
        this.stockPrice = price;
        notifyObservers(); // 价格变动时通知
    }
}

// 具体观察者(交易员)
class Trader implements Observer {
    private String name;
    public Trader(String name) { this.name = name; }
    
    @Override
    public void update(String message) {
        System.out.println(name + " notified: " + message);
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        StockExchange exchange = new StockExchange();
        Trader trader1 = new Trader("Alice");
        Trader trader2 = new Trader("Bob");
        
        exchange.registerObserver(trader1);
        exchange.registerObserver(trader2);
        exchange.setStockPrice(150.75);
    }
}

常用应用场景

  1. 事件驱动系统
    • GUI按钮点击事件(如C# WinForms、Java Swing)
    • 游戏引擎中的碰撞检测事件
  2. 发布-订阅模型
    • 新闻推送、社交媒体Feed更新
    • 微服务间的事件通知(如Kafka消息队列)
  3. 状态监控
    • 服务器资源使用率报警(CPU/Memory阈值触发)
    • IoT设备数据实时仪表盘
  4. 数据同步
    • 数据库变更同步到缓存(如Redis)
    • Excel单元格修改联动图表刷新
  5. MVC架构
    • 模型(Model)变更时自动更新视图(View)

关键注意事项

  1. 内存泄漏风险

    • 问题:观察者未注销时,主题持有其引用导致无法GC回收。
    • 解决:显式调用RemoveObserver()(如C# IDisposable接口、Java close()方法)。
  2. 通知顺序不可控

    • 问题:观察者接收顺序依赖注册顺序,可能影响业务逻辑。
    • 解决:引入优先级机制或保证观察者独立性。
  3. 性能瓶颈

    • 问题:观察者过多或更新逻辑复杂导致通知延迟。
    • 解决
      • 异步通知(如C# Task.Run、Java ExecutorService
      • 批量更新(合并多次状态变更)
  4. 循环依赖

    • 问题:观察者更新时反向修改主题状态,引发递归通知。
    • 解决:状态变更前检查if (oldState != newState)
  5. 线程安全问题

    • 问题:多线程环境下观察者列表动态修改导致ConcurrentModificationException(Java)。
    • 解决:使用线程安全集合(如CopyOnWriteArrayList)或同步锁。

架构设计建议

  1. 使用现有框架

    • C#:内置IObservable<T>/IObserver<T>接口
      public class Stock : IObservable<double> {
          private List<IObserver<double>> observers = new List<IObserver<double>>();
          public IDisposable Subscribe(IObserver<double> observer) { ... }
      }
      
    • Javajava.util.Observable类(已过时,推荐自定义实现)
  2. 事件与委托优化(C#专属)

    • 使用event关键字简化观察者管理:
      public class Publisher {
          public event Action<string> OnMessagePublished;
          public void Publish(string msg) => OnMessagePublished?.Invoke(msg);
      }
      
  3. 避免过度耦合

    • 观察者不应直接调用具体主题的方法,通过接口交互。
    • 主题通过NotifyObservers()传递最小必要数据(如事件对象而非整个主题引用)。
  4. 分布式场景扩展

    • 结合消息中间件(如RabbitMQ、Azure Service Bus)实现跨进程观察者模式。
  5. 测试策略

    • 使用Mock观察者验证主题通知逻辑。
    • 注入虚拟主题测试观察者行为。

模式优缺点

优点 缺点
主题与观察者解耦 意外更新链(级联通知)
动态添加/移除观察者 调试困难(间接调用链)
符合开闭原则(新增观察者无需改主题) 可能增加系统复杂性

适用性:适合状态变化触发跨模块更新,但需警惕过度使用导致系统难以追踪。

  1. 策略模式

策略模式详解:架构师视角

策略模式(Strategy Pattern)是一种行为设计模式,它定义一系列算法,封装每个算法,并使它们可以相互替换。策略模式让算法的变化独立于使用它的客户端。


核心结构

classDiagram
    class Context {
        -IStrategy strategy
        +SetStrategy(IStrategy)
        +ExecuteStrategy()
    }
    
    interface IStrategy {
        +Execute()
    }
    
    class ConcreteStrategyA {
        +Execute()
    }
    
    class ConcreteStrategyB {
        +Execute()
    }
    
    Context o--> IStrategy
    IStrategy <|.. ConcreteStrategyA
    IStrategy <|.. ConcreteStrategyB
  1. Context(上下文)

    • 维护策略对象的引用
    • 提供设置策略的方法
    • 执行策略的入口
  2. Strategy(策略接口)

    • 定义算法族的公共接口
  3. ConcreteStrategy(具体策略)

    • 实现策略接口的具体算法

C#/Java 代码示例

C# 实现
// 策略接口
public interface IPaymentStrategy 
{
    void ProcessPayment(decimal amount);
}

// 具体策略
public class CreditCardPayment : IPaymentStrategy
{
    public void ProcessPayment(decimal amount) 
        => Console.WriteLine($"Credit card: ${amount}");
}

public class PayPalPayment : IPaymentStrategy
{
    public void ProcessPayment(decimal amount) 
        => Console.WriteLine($"PayPal: ${amount}");
}

// 上下文
public class PaymentContext
{
    private IPaymentStrategy _strategy;
    
    public void SetStrategy(IPaymentStrategy strategy) 
        => _strategy = strategy;
    
    public void ExecutePayment(decimal amount) 
        => _strategy?.ProcessPayment(amount);
}

// 使用
var context = new PaymentContext();
context.SetStrategy(new CreditCardPayment());
context.ExecutePayment(100);  // 输出: Credit card: $100
Java 实现
// 策略接口
interface PaymentStrategy {
    void processPayment(BigDecimal amount);
}

// 具体策略
class WeChatPay implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("WeChat Pay: " + amount);
    }
}

class Alipay implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Alipay: " + amount);
    }
}

// 上下文
class PaymentContext {
    private PaymentStrategy strategy;
    
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void executePayment(BigDecimal amount) {
        if(strategy != null) {
            strategy.processPayment(amount);
        }
    }
}

// 使用
PaymentContext context = new PaymentContext();
context.setStrategy(new Alipay());
context.executePayment(new BigDecimal("200"));  // 输出: Alipay: 200

典型应用场景

  1. 支付系统(如示例):

    • 支持多种支付方式(信用卡/PayPal/加密货币)
    • 新增支付方式不影响现有逻辑
  2. 数据压缩/加密

    public interface ICompressionStrategy {
        byte[] Compress(byte[] data);
    }
    
    public class ZipCompression : ICompressionStrategy { ... }
    public class RarCompression : ICompressionStrategy { ... }
    
  3. 路由算法

    public interface IRoutingStrategy {
        Route CalculateRoute(Point start, Point end);
    }
    
    public class FastestRouteStrategy implements IRoutingStrategy { ... }
    public class EcoRouteStrategy implements IRoutingStrategy { ... }
    
  4. 表单验证

    public interface IValidationStrategy {
        bool Validate(string input);
    }
    
    public class EmailValidation : IValidationStrategy { ... }
    public class PhoneValidation : IValidationStrategy { ... }
    
  5. 电商折扣策略

    public interface IDiscountStrategy {
        BigDecimal applyDiscount(BigDecimal originalPrice);
    }
    
    public class VIPDiscount implements IDiscountStrategy { ... }
    public class FestivalDiscount implements IDiscountStrategy { ... }
    

架构建议与注意事项

  1. 避免策略膨胀

    • 当策略超过10个时,考虑使用策略工厂管理创建
    public class StrategyFactory {
        public IPaymentStrategy Create(string type) => 
            type switch {
                "CreditCard" => new CreditCardPayment(),
                "PayPal" => new PayPalPayment(),
                _ => throw new ArgumentException()
            };
    }
    
  2. 策略与状态模式区分

    • 策略模式:算法选择(客户端主动切换)
    • 状态模式:状态驱动(自动切换)
  3. 性能优化

    • 无状态策略可设计为单例减少对象创建
    public enum CompressionSingleton implements ICompressionStrategy {
        INSTANCE;
        
        @Override
        public byte[] compress(byte[] data) { ... }
    }
    
  4. 依赖注入集成

    • 通过DI容器管理策略生命周期
    services.AddTransient<IPaymentStrategy, CreditCardPayment>();
    services.AddTransient<IPaymentStrategy, PayPalPayment>();
    
  5. 策略组合

    • 支持策略的嵌套组合(装饰器模式)
    public class DiscountCombo implements IDiscountStrategy {
        private List<IDiscountStrategy> strategies;
        
        public BigDecimal applyDiscount(BigDecimal price) {
            for (IDiscountStrategy s : strategies) {
                price = s.applyDiscount(price);
            }
            return price;
        }
    }
    
  6. 文档规范

    • 使用XML注释/JavaDoc明确策略契约
    /**
     * @implSpec 实现必须保证线程安全
     */
    public interface ICachingStrategy { ... }
    

反模式警示

  1. 策略泄露

    // 错误:上下文暴露策略细节
    public class PaymentContext {
        public void ProcessCreditCard(CardDetails card) { ... }
    }
    
  2. 过度抽象

    • 简单条件判断无需策略模式
    // 不推荐:只有两种固定策略
    if(isVip) {
        new VIPDiscount().apply(price);
    } else {
        new RegularDiscount().apply(price);
    }
    
  3. 策略耦合

    // 错误:策略依赖具体实现
    public class Alipay : IPaymentStrategy {
        public void Process() {
            // 直接依赖微信支付
            new WeChatPay().Process(); 
        }
    }
    

性能考量

场景 建议方案
高频调用策略 使用轻量级策略对象
策略初始化成本高 延迟加载/Lazy初始化
需要动态切换策略 使用享元模式管理策略实例
策略执行需要上下文数据 通过参数传递避免状态存储

最佳实践总结

  1. 定义清晰策略边界:每个策略应解决单一问题
  2. 面向接口编程:上下文仅依赖策略接口
  3. 控制策略范围:避免创建过于细粒度的策略
  4. 结合工厂模式:解耦策略创建逻辑
  5. 单元测试策略:独立测试每个策略实现
  6. 监控策略执行:记录策略使用情况用于分析

架构师洞见:策略模式本质是将可变性封装在独立的策略对象中,符合开闭原则(OCP)。在微服务架构中,可将复杂策略实现为独立服务,通过策略网关进行路由,实现架构级策略管理。

  1. 命令模式

命令模式详解

命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为独立对象(命令),解耦请求的发送者(Invoker)和接收者(Receiver),支持请求排队、日志记录、撤销/重做等操作。


核心组件
角色 作用
Command 抽象命令接口,声明执行方法(如 Execute()
ConcreteCommand 具体命令,绑定接收者与动作,实现 Execute()(调用接收者的方法)
Receiver 实际执行业务逻辑的对象(如数据库操作、设备控制)
Invoker 触发命令的对象(如按钮、菜单),不直接依赖接收者
Client 创建命令对象并设置其接收者

C# 实现示例

// 命令接口
public interface ICommand {
    void Execute();
    void Undo(); // 支持撤销
}

// 接收者:实际执行操作的对象
public class Light {
    public void TurnOn() => Console.WriteLine("Light is ON");
    public void TurnOff() => Console.WriteLine("Light is OFF");
}

// 具体命令
public class LightOnCommand : ICommand {
    private Light _light;
    public LightOnCommand(Light light) => _light = light;
    public void Execute() => _light.TurnOn();
    public void Undo() => _light.TurnOff(); // 撤销操作
}

// 调用者(如遥控器按钮)
public class RemoteControl {
    private ICommand _command;
    public void SetCommand(ICommand command) => _command = command;
    public void PressButton() {
        _command.Execute();
        _history.Push(_command); // 记录历史用于撤销
    }
    private Stack<ICommand> _history = new Stack<ICommand>();
}

// 客户端
var light = new Light();
var lightOn = new LightOnCommand(light);
var remote = new RemoteControl();
remote.SetCommand(lightOn);
remote.PressButton(); // 输出:"Light is ON"

Java 实现示例

// 命令接口
interface Command {
    void execute();
    void undo();
}

// 接收者
class Light {
    public void turnOn() { System.out.println("Light ON"); }
    public void turnOff() { System.out.println("Light OFF"); }
}

// 具体命令
class LightOnCommand implements Command {
    private Light light;
    public LightOnCommand(Light light) { this.light = light; }
    @Override
    public void execute() { light.turnOn(); }
    @Override
    public void undo() { light.turnOff(); }
}

// 调用者
class RemoteControl {
    private Command command;
    private Stack<Command> history = new Stack<>();
    public void setCommand(Command command) { this.command = command; }
    public void pressButton() {
        command.execute();
        history.push(command);
    }
}

// 客户端
public static void main(String[] args) {
    Light light = new Light();
    Command lightOn = new LightOnCommand(light);
    RemoteControl remote = new RemoteControl();
    remote.setCommand(lightOn);
    remote.pressButton(); // 输出:"Light ON"
}

常用应用场景

  1. GUI 操作
    • 按钮点击、菜单命令(如文本编辑器的复制/粘贴)
    • 示例:将每个操作封装为命令对象,支持撤销/重做。
  2. 任务队列与日志
    • 将请求排队(如线程池任务调度)
    • 记录操作日志(用于审计或崩溃恢复)
  3. 事务行为
    • 数据库事务的原子操作(失败时执行反向命令回滚)
  4. 宏命令(组合命令)
    • 一键执行多个命令(如批量处理文件)
  5. 异步任务管理
    • 将耗时操作封装为命令,由后台线程执行

注意事项与架构建议

注意事项
  1. 避免过度设计:简单请求(如直接函数调用)无需使用命令模式。
  2. 内存消耗:每个命令都是一个独立对象,大量命令可能增加内存开销。
  3. 撤销实现复杂性
    • 需存储额外状态(如 Memento 模式)或反向操作逻辑。
    • 多次撤销可能需维护命令历史栈。
架构建议
  1. 结合其他模式增强能力
    • 组合模式:实现宏命令(组合多个子命令)。
    • 备忘录模式:存储命令执行前的状态,支持完美撤销。
    // 示例:宏命令(C#)
    public class MacroCommand : ICommand {
        private List<ICommand> _commands = new List<ICommand>();
        public void Add(ICommand cmd) => _commands.Add(cmd);
        public void Execute() => _commands.ForEach(cmd => cmd.Execute());
    }
    
  2. 依赖注入
    • 通过 DI 容器管理命令和接收者,提高可测试性。
  3. 线程安全
    • 多线程环境下,命令对象需设计为无状态或使用锁机制。
  4. 空命令对象
    • 提供 NullCommand 避免 Invoker 对命令的空值检查。
    // Java 空命令示例
    class NullCommand implements Command {
        @Override public void execute() {} 
        @Override public void undo() {}
    }
    
  5. 命令持久化
    • 序列化命令对象,支持重启后恢复操作(如游戏存档)。

设计原则验证

  • 单一职责原则:命令对象仅封装请求,接收者专注业务逻辑。
  • 开闭原则:新增命令无需修改 Invoker 或 Receiver。
  • 松耦合:Invoker 仅依赖抽象命令,与接收者解耦。

总结

适用场景:需要解耦请求发送者与接收者、支持撤销/重做、任务队列或日志的场景。
避坑指南

  • 简单场景避免滥用,优先考虑函数式编程替代(如 C# Action/Java Runnable)。
  • 为高频命令实现轻量级版本(如共享无状态接收者)。
  • 撤销功能需在早期设计阶段考虑,避免后期重构。

命令模式通过封装请求为对象,显著提升系统的灵活性与扩展性,是复杂操作管理的核心模式之一。

  1. 状态模式

状态模式(State Pattern)详解

核心概念

状态模式是一种行为型设计模式,允许对象在内部状态改变时改变其行为,使对象看起来像是修改了它的类。该模式将状态相关的行为封装到独立的类中,并通过委托机制让上下文对象在不同状态下表现出不同行为。

核心组件
  1. Context(上下文)
    • 持有当前状态对象的引用
    • 定义客户端交互接口
    • 提供状态切换方法
  2. State(抽象状态)
    • 定义状态接口,声明状态相关行为
  3. ConcreteState(具体状态)
    • 实现状态接口,封装特定状态下的行为
C# 实现示例
// 抽象状态
public interface IOrderState
{
    void Confirm(OrderContext context);
    void Cancel(OrderContext context);
    void Ship(OrderContext context);
}

// 具体状态:待确认
public class PendingState : IOrderState
{
    public void Confirm(OrderContext context) 
        => context.SetState(new ConfirmedState());
    
    public void Cancel(OrderContext context) 
        => context.SetState(new CancelledState());
    
    public void Ship(OrderContext context) 
        => throw new InvalidOperationException("待确认订单不能发货");
}

// 具体状态:已确认
public class ConfirmedState : IOrderState
{
    public void Confirm(OrderContext context) 
        => throw new InvalidOperationException("订单已确认");
    
    public void Cancel(OrderContext context) 
        => context.SetState(new CancelledState());
    
    public void Ship(OrderContext context) 
        => context.SetState(new ShippedState());
}

// 上下文
public class OrderContext
{
    private IOrderState _state = new PendingState();
    
    public void SetState(IOrderState state) => _state = state;
    
    public void Confirm() => _state.Confirm(this);
    public void Cancel() => _state.Cancel(this);
    public void Ship() => _state.Ship(this);
}

// 使用
var order = new OrderContext();
order.Confirm();  // 状态转为ConfirmedState
order.Ship();     // 状态转为ShippedState
Java 实现示例
// 抽象状态
interface OrderState {
    void confirm(OrderContext context);
    void cancel(OrderContext context);
    void ship(OrderContext context);
}

// 具体状态:待确认
class PendingState implements OrderState {
    public void confirm(OrderContext context) {
        context.setState(new ConfirmedState());
    }
    public void cancel(OrderContext context) {
        context.setState(new CancelledState());
    }
    public void ship(OrderContext context) {
        throw new IllegalStateException("待确认订单不能发货");
    }
}

// 上下文
class OrderContext {
    private OrderState state = new PendingState();
    
    void setState(OrderState state) { this.state = state; }
    
    void confirm() { state.confirm(this); }
    void cancel() { state.cancel(this); }
    void ship() { state.ship(this); }
}

典型应用场景

  1. 订单/工作流系统

    • 订单状态(待支付/已发货/已完成)
    • 审批流程(草稿/审批中/已批准)
  2. 游戏角色状态

    • 角色行为(站立/奔跑/跳跃/攻击)
    • 状态切换时行为变化(如跳跃时不可攻击)
  3. 硬件控制

    • 电梯状态(停止/运行/故障)
    • 打印机状态(空闲/打印/卡纸)
  4. UI 组件交互

    • 按钮状态(正常/禁用/悬停)
    • 动画控件状态(开始/暂停/停止)
  5. 网络协议处理

    • TCP连接状态(建立连接/数据传输/断开连接)
    • 协议状态机实现

注意事项

  1. 避免状态膨胀

    • 当状态超过10个时需重新评估设计
    • 考虑使用状态表(State Table)或状态机库替代
  2. 状态转换控制

    • 转换逻辑放在Context还是State?
      • Context控制:集中管理转换规则(推荐)
      • State控制:增加状态间耦合(慎用)
  3. 状态共享

    • 无内部状态的状态对象可设计为单例
    public class CancelledState : IOrderState 
    {
        public static readonly IOrderState Instance = new CancelledState();
        // ... 实现方法
    }
    
  4. 初始化问题

    • 确保Context初始状态有效
    • 使用工厂方法初始化默认状态
  5. 并发安全

    • 多线程环境下需同步状态切换
    • 推荐使用不可变状态对象

架构建议

1. 分层状态机
payment
cancel
ship
confirm
Unpaid
Paid
Cancelled
Shipped
Completed
  • 复杂场景使用分层状态(HFSM)
  • 子状态可继承父状态行为
2. 与策略模式对比
状态模式 策略模式
状态自动转换 策略手动切换
状态知晓上下文 策略独立于上下文
状态间存在关联 策略可独立替换
3. 性能优化
  • 状态预创建:初始化时创建所有状态对象
  • 轻量状态:避免在状态中存储上下文数据
4. 测试建议
  • 为每个状态类编写独立单元测试
  • 验证非法状态转换的异常处理
  • 使用Mock对象测试状态间交互
5. 与其它模式协作
  • 结合享元模式:共享无状态的状态对象
  • 使用备忘录模式:实现状态历史回溯
  • 通过观察者模式:通知状态变更事件

反模式警示

  1. 上帝状态对象

    // 错误示范:一个状态类处理所有逻辑
    public class GodState : IOrderState 
    {
        public void Handle(OrderContext ctx) 
        {
            if(ctx.Status == Status.Pending) {...}
            else if(ctx.Status == Status.Confirmed) {...} 
            // 违反开闭原则
        }
    }
    
  2. 循环依赖

    • 状态类不应直接引用其它具体状态类
    • 通过Context进行状态切换解耦
  3. 忽略状态重置

    • 长时间运行的系统需设计状态重置机制
    • 提供Reset()方法恢复初始状态

最佳实践总结

  1. 明确状态边界:每个状态对应唯一行为集合
  2. 单向依赖原则:状态类只依赖抽象Context
  3. 有限状态转换:使用状态转换图定义合法路径
  4. 文档驱动:使用PlantUML等工具维护状态图
  5. 防御式编程:在Context中验证状态转换合法性

架构师建议:在核心业务逻辑(如订单/支付)中使用状态模式,能显著提升系统可维护性。对于超复杂状态机(>20状态),推荐使用专门的State Machine框架(如Stateless for .NET或Spring State Machine)。

  1. 责任链

责任链模式详解

模式定义

责任链(Chain of Responsibility)是一种行为型设计模式,允许多个对象按顺序处理请求,形成处理链。请求沿链传递直到被处理或到达链尾,实现发送者与接收者的解耦。

核心组件
  1. Handler(抽象处理者)
    • 定义处理请求的接口
    • 持有下一个处理者的引用(可选)
  2. ConcreteHandler(具体处理者)
    • 实现请求处理逻辑
    • 决定是否处理请求或传递给下一处理者
  3. Request(请求对象)
    • 封装请求数据

C# 实现示例

// 请求类
public class PurchaseRequest {
    public decimal Amount { get; set; }
}

// 抽象处理者
public abstract class Approver {
    protected Approver? NextApprover;
    public void SetNext(Approver next) => NextApprover = next;
    public abstract void Process(PurchaseRequest request);
}

// 具体处理者:经理
public class Manager : Approver {
    public override void Process(PurchaseRequest request) {
        if (request.Amount <= 1000) {
            Console.WriteLine($"经理审批: {request.Amount}元");
        } else if (NextApprover != null) {
            NextApprover.Process(request); // 传递请求
        }
    }
}

// 具体处理者:总监
public class Director : Approver {
    public override void Process(PurchaseRequest request) {
        if (request.Amount <= 5000) {
            Console.WriteLine($"总监审批: {request.Amount}元");
        } else if (NextApprover != null) {
            NextApprover.Process(request);
        }
    }
}

// 使用
var manager = new Manager();
var director = new Director();
manager.SetNext(director);

manager.Process(new PurchaseRequest { Amount = 800 });   // 经理处理
manager.Process(new PurchaseRequest { Amount = 4500 });  // 总监处理

Java 实现示例

// 抽象处理者
abstract class Approver {
    protected Approver next;
    public void setNext(Approver next) { this.next = next; }
    public abstract void process(PurchaseRequest request);
}

// 具体处理者
class Manager extends Approver {
    @Override
    public void process(PurchaseRequest request) {
        if (request.getAmount() <= 1000) {
            System.out.println("经理审批: " + request.getAmount());
        } else if (next != null) {
            next.process(request); // 传递请求
        }
    }
}

// 使用
Approver manager = new Manager();
Approver director = new Director();
manager.setNext(director);

manager.process(new PurchaseRequest(800));   // 经理处理
manager.process(new PurchaseRequest(4500));  // 总监处理

常用场景

  1. 多级审批系统
    • 费用报销、请假审批(不同金额/时长由不同层级审批)
  2. 请求过滤/中间件
    • Web框架的过滤器链(如Spring Security)
    • 日志记录、身份验证、数据清洗
  3. 事件处理
    • GUI事件冒泡(如Java AWT/Swing)
  4. 异常处理
    • 多级异常捕获机制(如Java的try-catch链)
  5. 日志分级处理
    • DEBUG → INFO → WARN → ERROR 链式传递

注意事项

  1. 链的终止条件
    • 必须确保链有终点,避免请求无限循环
    • 可在基类添加默认处理逻辑(如抛出异常或日志警告)
  2. 性能考量
    • 长链可能导致性能下降,避免高频场景使用
  3. 调试复杂性
    • 请求传递路径不易跟踪,需完善日志
  4. 处理者顺序敏感
    • 链的顺序影响行为(如权限检查应先于业务处理)
  5. 请求丢失风险
    • 确保所有处理者正确传递未处理的请求

架构建议

  1. 动态链构建
    • 使用配置文件或依赖注入动态组装链(如Spring的@Order
    // Spring示例:按Order注解排序
    @Component @Order(1)
    class AuthFilter implements Filter { ... }
    
  2. 组合模式融合
    • 复杂场景下,用组合模式构建树形责任链
  3. 模板方法优化
    • 在抽象类中封装传递逻辑,子类聚焦核心处理
    public abstract class Approver {
        protected virtual bool CanHandle(PurchaseRequest r) => false;
        public void Process(PurchaseRequest r) {
            if (CanHandle(r)) Handle(r);
            else NextApprover?.Process(r);
        }
        protected abstract void Handle(PurchaseRequest r);
    }
    
  4. 短路机制
    • 特定场景可中断传递(如权限验证失败时直接返回)
  5. 监控扩展
    • 添加链执行统计(如处理时长、成功率)

经典应用

框架/系统 应用场景
Spring MVC 拦截器链(HandlerInterceptor)
Servlet Filter 请求过滤链
Log4j/Logback 日志级别过滤链
Netty ChannelHandler处理链

责任链模式通过解耦请求发送者和处理者,显著提升系统扩展性。适用于需动态调整处理流程的场景,但需谨慎处理链的终止条件和性能影响。
15. 迭代器

迭代器模式详解(Iterator Pattern)

模式定义

迭代器模式是一种行为设计模式,提供一种方法顺序访问聚合对象中的各个元素,而无需暴露该对象的内部表示。它通过将遍历逻辑从聚合对象中分离,实现“单一职责原则”,同时支持多种遍历方式。

核心组件
组件 作用 示例接口
迭代器接口 定义遍历操作(如 next, hasNext) IEnumerator (C#) / Iterator (Java)
具体迭代器 实现迭代器接口,持有聚合对象的引用并跟踪遍历位置 ListEnumerator
聚合接口 定义创建迭代器的方法 IEnumerable (C#) / Iterable (Java)
具体聚合类 实现聚合接口,返回具体迭代器实例 List<T>

C# 实现示例

// 迭代器接口
public interface IIterator
{
    bool HasNext();
    object Next();
}

// 聚合接口
public interface IAggregate
{
    IIterator CreateIterator();
}

// 具体聚合类
public class ConcreteAggregate : IAggregate
{
    private object[] _items = { "A", "B", "C" };

    public IIterator CreateIterator()
    {
        return new ConcreteIterator(this);
    }

    public int Count => _items.Length;
    public object this[int index] => _items[index];
}

// 具体迭代器
public class ConcreteIterator : IIterator
{
    private readonly ConcreteAggregate _aggregate;
    private int _index = 0;

    public ConcreteIterator(ConcreteAggregate aggregate)
    {
        _aggregate = aggregate;
    }

    public bool HasNext() => _index < _aggregate.Count;
    public object Next() => _aggregate[_index++];
}

// 使用
var aggregate = new ConcreteAggregate();
var iterator = aggregate.CreateIterator();
while (iterator.HasNext())
{
    Console.WriteLine(iterator.Next()); // 输出 A, B, C
}

Java 实现示例

// 迭代器接口
public interface Iterator<T> {
    boolean hasNext();
    T next();
}

// 聚合接口
public interface Iterable<T> {
    Iterator<T> createIterator();
}

// 具体聚合类
public class ConcreteAggregate implements Iterable<String> {
    private String[] items = {"A", "B", "C"};

    @Override
    public Iterator<String> createIterator() {
        return new ConcreteIterator();
    }

    private class ConcreteIterator implements Iterator<String> {
        private int index = 0;

        @Override
        public boolean hasNext() {
            return index < items.length;
        }

        @Override
        public String next() {
            return items[index++];
        }
    }
}

// 使用
ConcreteAggregate aggregate = new ConcreteAggregate();
Iterator<String> iterator = aggregate.createIterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next()); // 输出 A, B, C
}

常用场景

  1. 遍历复杂数据结构

    • 树形结构(二叉树、多叉树)
    • 图结构(DFS/BFS遍历器)
    • 自定义集合(如分页查询结果集)
  2. 解耦客户端与集合实现

    • 客户端仅依赖迭代器接口,不依赖具体集合类(如 List vs Set
    • 示例:统一遍历数据库查询结果与内存集合
  3. 延迟加载/流式处理

    • 大数据集分批加载(如数据库分页迭代器)
    • 流处理管道(如 Java Stream API 的迭代器实现)
  4. 多线程安全遍历

    • 提供快照迭代器(如 CopyOnWriteArrayList
    • 并发修改检测(Java 的 ConcurrentModificationException

注意事项

  1. 线程安全问题

    • 迭代过程中修改集合会导致未定义行为(如 Java 的 fail-fast 机制)
    • 解决方案:使用并发集合或克隆数据
  2. 资源泄漏风险

    • 迭代器持有集合引用可能导致内存泄漏
    • 特别在长生命周期迭代器(如缓存中)需注意
  3. 性能开销

    • 每步操作需状态检查(如 hasNext()
    • 复杂数据结构(如树)的迭代器实现可能低效
  4. 空迭代器处理

    • 空集合应返回有效的“空迭代器”,而非 null

架构设计建议

  1. 优先使用语言内置迭代器

    • C#:IEnumerable<T> + yield return
      public IEnumerable<int> GetValues() {
          for (int i = 0; i < 10; i++) {
              yield return i; // 自动生成迭代器
          }
      }
      
    • Java:实现 Iterable<T> + Lambda
      List<Integer> list = Arrays.asList(1, 2, 3);
      list.forEach(System.out::println); // 内部迭代
      
  2. 为自定义集合提供标准迭代器

    • 实现语言标准接口(如 Java 的 Iterable),方便与现有库集成
    • 示例:自定义树结构实现 Iterable<Node>
  3. 支持多种遍历策略

    • 通过工厂方法返回不同迭代器:
      public Iterator<T> createIterator(TraversalType type) {
          switch(type) {
              case IN_ORDER: return new InOrderIterator();
              case PRE_ORDER: return new PreOrderIterator();
          }
      }
      
  4. 防御性编程

    • 迭代器实现应检测并发修改:
      public class SafeIterator {
          private final int expectedModCount;
          public T next() {
              if (modCount != expectedModCount) 
                  throw new ConcurrentModificationException();
              // ...
          }
      }
      
  5. 避免暴露内部状态

    • 迭代器不应提供修改集合的方法(如 remove() 需谨慎设计)
    • 分离只读迭代器与读写迭代器接口

典型应用案例

  • 集合框架
    Java 的 ArrayList.iterator(), C# 的 List<T>.GetEnumerator()

  • 数据库访问
    ORM 框架的查询结果迭代(如 Entity Framework 的 IQueryable

  • 文件/网络流处理
    按行读取大文件:

    foreach (var line in File.ReadLines("large.txt")) {
        // 逐行处理,避免全量加载
    }
    
  • 组合模式树遍历
    递归遍历 UI 组件树:

    public class UIComponent implements Iterable<UIComponent> {
        private List<UIComponent> children = new ArrayList<>();
        public Iterator<UIComponent> iterator() {
            return new DepthFirstIterator(this);
        }
    }
    

总结

迭代器模式通过抽象遍历过程,实现了:

  1. 解耦:分离集合结构与遍历逻辑
  2. 扩展性:支持多种遍历方式且不修改聚合类
  3. 简洁性:统一使用 foreach 等语法糖

黄金法则:当你的集合需要提供遍历能力时,优先实现语言标准迭代协议(C# 的 IEnumerable/Java 的 Iterable),而非自定义接口。这能最大化兼容性和可维护性。
16. 中介者

中介者模式(Mediator Pattern)详解

中介者模式是一种行为设计模式,通过引入中介对象封装一组对象之间的交互,降低对象间的直接耦合。核心思想是 “对象间不直接通信,而是通过中介者转发请求”

模式结构
«interface»
Mediator
+Notify(sender: Colleague, event: string)
ConcreteMediator
-colleagues: List<Colleague>
+Register(colleague: Colleague)
+Notify(sender: Colleague, event: string)
Colleague
-mediator: Mediator
+SetMediator(mediator: Mediator)
ConcreteColleagueA
+DoOperation()
ConcreteColleagueB
+HandleEvent()

C# 示例:智能家居控制系统

// 中介者接口
public interface ISmartHomeMediator
{
    void Register(Device device);
    void Notify(Device sender, string eventType);
}

// 具体中介者
public class HomeAutomationHub : ISmartHomeMediator
{
    private readonly List<Device> _devices = new();

    public void Register(Device device) => _devices.Add(device);

    public void Notify(Device sender, string eventType)
    {
        foreach (var device in _devices.Where(d => d != sender))
        {
            device.HandleEvent(eventType);
        }
    }
}

// 抽象同事类
public abstract class Device
{
    protected ISmartHomeMediator Mediator;
    public void SetMediator(ISmartHomeMediator mediator) => Mediator = mediator;
    public abstract void HandleEvent(string eventType);
}

// 具体设备
public class Light : Device
{
    public override void HandleEvent(string eventType)
    {
        if (eventType == "MOTION_DETECTED")
            Console.WriteLine("Light turns ON");
        else if (eventType == "NO_MOTION")
            Console.WriteLine("Light turns OFF");
    }
}

public class SecurityCamera : Device
{
    public void DetectMotion() => Mediator.Notify(this, "MOTION_DETECTED");
}

// 使用
var hub = new HomeAutomationHub();
var light = new Light();
var camera = new SecurityCamera();

light.SetMediator(hub);
camera.SetMediator(hub);
hub.Register(light);
hub.Register(camera);

camera.DetectMotion(); // 触发所有设备响应

Java 示例:航空交通管制系统

// 中介者接口
interface AirTrafficControl {
    void registerFlight(Flight flight);
    void sendWarning(Flight sender, String message);
}

// 具体中介者
class ControlTower implements AirTrafficControl {
    private List<Flight> flights = new ArrayList<>();

    public void registerFlight(Flight flight) {
        flights.add(flight);
    }

    public void sendWarning(Flight sender, String message) {
        for (Flight flight : flights) {
            if (flight != sender) {
                flight.receiveWarning(message);
            }
        }
    }
}

// 抽象同事类
abstract class Flight {
    protected AirTrafficControl atc;
    public void setATC(AirTrafficControl atc) {
        this.atc = atc;
    }
    public abstract void receiveWarning(String message);
}

// 具体航班
class CargoFlight extends Flight {
    public void reportPosition() {
        atc.sendWarning(this, "CARGO_FLIGHT at 10,000m");
    }

    @Override
    public void receiveWarning(String message) {
        System.out.println("Cargo flight received: " + message);
    }
}

// 使用
ControlTower tower = new ControlTower();
CargoFlight flight1 = new CargoFlight();
CargoFlight flight2 = new CargoFlight();

flight1.setATC(tower);
flight2.setATC(tower);
tower.registerFlight(flight1);
tower.registerFlight(flight2);

flight1.reportPosition(); // 触发其他航班接收警告

常用应用场景

  1. GUI组件交互
    • 按钮/文本框/下拉菜单通过中介者协调(如:表单验证、状态联动)
  2. 分布式系统协调
    • 微服务通过消息中介(如RabbitMQ)解耦通信
  3. 游戏开发
    • 角色/道具/环境通过游戏主循环中介交互
  4. 工作流引擎
    • 审批节点通过流程引擎中介传递任务
  5. 聊天系统
    • 用户通过聊天室中介广播消息

注意事项与架构建议

⚠️ 注意事项
  1. 避免上帝对象
    • 中介者不应包含过多业务逻辑(违反单一职责原则)
  2. 性能考量
    • 高频通信场景需优化中介者转发效率
  3. 调试复杂性
    • 交互链路间接化增加调试难度
✅ 架构建议
  1. 分层中介者
    全局中介者
    模块中介者1
    模块中介者2
    组件A
    组件B
    组件C
  2. 与观察者模式结合
    • 用事件机制实现中介通知(INotifyPropertyChanged
  3. 接口隔离原则
    • 为不同组件定义专用中介接口
    public interface IDeviceMediator {
        void NotifyLightSensor();
        void NotifyThermostat();
    }
    
  4. DI容器集成
    • 通过依赖注入管理中介者生命周期(.NET Core/Spring)
  5. 有限使用场景
    • 仅在对象间存在复杂网状关系时使用

模式对比

模式 特点 适用场景
中介者 集中控制多对象交互 复杂组件网络
观察者 一对多依赖关系 事件通知系统
外观 简化子系统访问接口 复杂子系统封装

黄金法则:当系统出现"蜘蛛网式耦合"(对象间引用混乱)时,优先考虑中介者模式重构。

  1. 备忘录

备忘录模式(Memento Pattern)详解

模式定义

备忘录模式是一种行为设计模式,它允许在不破坏对象封装性的前提下捕获并外部化对象的内部状态,以便后续可将该对象恢复到先前的状态。核心目标是提供状态的快照机制回滚能力

核心角色
  1. Originator(发起人)

    • 需要保存状态的对象(如文档编辑器、游戏角色)
    • 提供创建备忘录(CreateMemento())和恢复状态(RestoreMemento())的方法
  2. Memento(备忘录)

    • 存储Originator内部状态的不可变对象(通常设计为只读)
    • 通过窄接口(如GetState())暴露状态,保护封装性
  3. Caretaker(管理者)

    • 负责存储和管理备忘录(如历史记录栈)
    • 无权修改或读取备忘录内容(符合迪米特法则)

常用场景示例

场景1:文档编辑器的撤销/重做(C#)
// Memento
public class DocumentMemento
{
    public string Content { get; } // 只读属性保护状态
    public DocumentMemento(string content) => Content = content;
}

// Originator
public class Document
{
    public string Content { get; set; }

    public DocumentMemento CreateMemento() => new(Content);
    
    public void RestoreMemento(DocumentMemento memento) 
        => Content = memento.Content;
}

// Caretaker
public class HistoryTracker
{
    private readonly Stack<DocumentMemento> _history = new();
    
    public void SaveState(Document doc) 
        => _history.Push(doc.CreateMemento());
    
    public void Undo(Document doc)
    {
        if (_history.Count > 0) doc.RestoreMemento(_history.Pop());
    }
}

// 使用
var doc = new Document();
var history = new HistoryTracker();

doc.Content = "Version 1";
history.SaveState(doc);  // 保存状态

doc.Content = "Version 2"; // 修改内容
history.Undo(doc);       // 撤销到Version 1
场景2:游戏角色状态存档(Java)
// Memento
public class PlayerMemento {
    private final int health;
    private final String position;
    
    public PlayerMemento(int health, String position) {
        this.health = health;
        this.position = position;
    }
    
    public int getHealth() { return health; }  // 只提供Getter
    public String getPosition() { return position; }
}

// Originator
public class Player {
    private int health;
    private String position;
    
    public PlayerMemento save() {
        return new PlayerMemento(health, position);
    }
    
    public void load(PlayerMemento memento) {
        this.health = memento.getHealth();
        this.position = memento.getPosition();
    }
}

// Caretaker
public class SaveManager {
    private Map<String, PlayerMemento> saves = new HashMap<>();
    
    public void saveGame(String slot, Player player) {
        saves.put(slot, player.save());
    }
    
    public void loadGame(String slot, Player player) {
        if (saves.containsKey(slot)) player.load(saves.get(slot));
    }
}

注意事项与架构建议

注意事项
  1. 内存消耗

    • 频繁保存大对象状态可能导致内存溢出(如高清图片编辑)
    • 解决方案:增量备份、压缩存储、限制历史记录数量
  2. 封装性保护

    • 备忘录必须严格限制状态访问(C#用internal修饰,Java用包级私有)
    • 禁止Caretaker直接修改备忘录内容
  3. 深拷贝问题

    • 对象包含引用类型时需深拷贝(如集合、嵌套对象)
    • 示例:DocumentMemento中的Content是字符串(不可变),无需深拷
  4. 生命周期管理

    • 长时间未使用的备忘录应及时清除(如LRU缓存策略)
架构建议
  1. 性能优化

    // 仅保存差异状态(增量备份)
    public class DiffMemento {
        public string ChangedText { get; }
        public int StartIndex { get; }
        // ... 其他差异元数据
    }
    
  2. 支持多级撤销

    // Caretaker中使用双栈实现
    Stack<Memento> undoStack = new Stack<>();
    Stack<Memento> redoStack = new Stack<>();
    
  3. 持久化扩展

    • 备忘录可序列化为JSON/二进制存储到数据库
    • 示例:
      public string SerializeMemento(DocumentMemento m) 
          => JsonConvert.SerializeObject(m);
      
  4. 安全控制

    • 对备忘录加密(如游戏存档防篡改)
    • 添加版本号兼容旧版状态
  5. 结合其他模式

    • 命令模式:将备忘录绑定到命令对象实现事务操作
    • 原型模式:通过克隆生成备忘录减少开销

经典应用案例

领域 应用实例
文本编辑器 Word/VS Code的撤销栈
图形设计软件 Photoshop历史记录
游戏开发 角色状态存档/关卡进度保存
数据库系统 事务回滚(Transaction Rollback)
版本控制系统 Git的commit/checkout机制

黄金法则:当系统需要“时间机器”功能时优先考虑备忘录模式,但需警惕状态爆炸问题。建议通过[Serializable](C#)或Serializable接口(Java)支持跨进程状态恢复。

  1. 访问者

访问者模式详解

访问者模式(Visitor Pattern)是一种行为型设计模式,允许你将算法与操作的对象结构分离。它通过将操作逻辑移至独立的访问者类中,实现在不修改现有类结构的前提下添加新操作。

核心思想

  • 双重分派(Double Dispatch):通过组合方法调用实现运行时多态
  • 分离关注点:数据结构与数据操作解耦
  • 开放封闭原则:新增操作只需添加新的访问者,无需修改元素类

模式结构

accept调用visit
accept调用visit
«interface»
Visitor
+visitElementA(ElementA)
+visitElementB(ElementB)
ConcreteVisitor1
+visitElementA(ElementA)
+visitElementB(ElementB)
«interface»
Element
+accept(Visitor)
ElementA
+accept(Visitor)
+featureA()
ElementB
+accept(Visitor)
+featureB()

C# 实现示例

// 元素接口
public interface IElement
{
    void Accept(IVisitor visitor);
}

// 具体元素A
public class ConcreteElementA : IElement
{
    public void FeatureA() => Console.WriteLine("Feature A");
    public void Accept(IVisitor visitor) => visitor.VisitElementA(this);
}

// 具体元素B
public class ConcreteElementB : IElement
{
    public void FeatureB() => Console.WriteLine("Feature B");
    public void Accept(IVisitor visitor) => visitor.VisitElementB(this);
}

// 访问者接口
public interface IVisitor
{
    void VisitElementA(ConcreteElementA element);
    void VisitElementB(ConcreteElementB element);
}

// 具体访问者
public class ConcreteVisitor : IVisitor
{
    public void VisitElementA(ConcreteElementA element)
    {
        Console.WriteLine("Visitor processing ElementA");
        element.FeatureA();
    }

    public void VisitElementB(ConcreteElementB element)
    {
        Console.WriteLine("Visitor processing ElementB");
        element.FeatureB();
    }
}

// 对象结构
public class ObjectStructure
{
    private readonly List<IElement> _elements = new();

    public void Attach(IElement element) => _elements.Add(element);
    public void Detach(IElement element) => _elements.Remove(element);
    
    public void Accept(IVisitor visitor)
    {
        foreach (var element in _elements)
        {
            element.Accept(visitor);
        }
    }
}

Java 实现示例

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// 具体元素A
class ConcreteElementA implements Element {
    public void featureA() {
        System.out.println("Feature A");
    }
    
    @Override
    public void accept(Visitor visitor) {
        visitor.visitElementA(this);
    }
}

// 具体元素B
class ConcreteElementB implements Element {
    public void featureB() {
        System.out.println("Feature B");
    }
    
    @Override
    public void accept(Visitor visitor) {
        visitor.visitElementB(this);
    }
}

// 访问者接口
interface Visitor {
    void visitElementA(ConcreteElementA element);
    void visitElementB(ConcreteElementB element);
}

// 具体访问者
class ConcreteVisitor implements Visitor {
    @Override
    public void visitElementA(ConcreteElementA element) {
        System.out.println("Visitor processing ElementA");
        element.featureA();
    }

    @Override
    public void visitElementB(ConcreteElementB element) {
        System.out.println("Visitor processing ElementB");
        element.featureB();
    }
}

// 对象结构
class ObjectStructure {
    private final List<Element> elements = new ArrayList<>();
    
    public void attach(Element element) {
        elements.add(element);
    }
    
    public void detach(Element element) {
        elements.remove(element);
    }
    
    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

常用应用场景

  1. 复杂对象结构操作

    • 抽象语法树(AST)处理(编译器设计)
    • 文档对象模型(DOM)处理
    • UI组件树遍历
  2. 跨类层次的操作

    • 报表生成(不同业务对象生成不同格式报表)
    • 序列化/反序列化系统
    • 权限检查系统
  3. 分离关注点

    • 数据收集与统计(如电商订单各元素价格计算)
    • 多格式导出系统(XML/JSON/CSV)
    • 游戏实体行为处理(不同NPC类型的不同交互)
  4. 扩展框架功能

    • IDE插件系统
    • 工作流引擎扩展点
    • 规则引擎执行器

关键注意事项

  1. 元素稳定性要求

    • 适用场景:元素类结构稳定,但操作频繁变化
    • 不适用场景:元素类需要频繁添加新类型
  2. 封装性破坏风险

    • 访问者通常需要访问元素内部状态
    • 解决方案:
      • 提供受控访问接口
      • 使用友元关系(C++)
      • 包级私有访问(Java)
  3. 循环依赖问题

    • 元素和访问者相互引用
    • 解决方案:通过接口解耦,避免具体类依赖
  4. 遍历责任归属

    • 明确对象结构负责遍历还是访问者负责
    • 推荐:对象结构控制遍历顺序(如组合模式)

架构设计建议

  1. 访问者层次设计

    抽象访问者
    报表生成
    数据导出
    校验器
    PDFReportVisitor
    ExcelReportVisitor
  2. 与组合模式结合

    public class CompositeElement : IElement
    {
        private readonly List<IElement> _children = new();
        
        public void Add(IElement element) => _children.Add(element);
        
        public void Accept(IVisitor visitor)
        {
            visitor.VisitComposite(this);
            foreach (var child in _children)
            {
                child.Accept(visitor);
            }
        }
    }
    
  3. 访问者状态管理

    • 有状态访问者:适合数据聚合场景(如价格计算)
    • 无状态访问者:适合纯操作场景(如格式转换)
  4. 性能优化策略

    • 访问者缓存:复用访问者实例
    • 遍历优化:增量遍历大型结构
    • 并行处理:线程安全访问者
  5. 访问控制机制

    • 基于角色的访问控制:
    public class RoleBasedVisitor implements Visitor {
        private final UserRole role;
        
        public RoleBasedVisitor(UserRole role) {
            this.role = role;
        }
        
        @Override
        public void visitElementA(ConcreteElementA element) {
            if(role.canAccess(element)) {
                // 执行操作
            }
        }
    }
    

最佳实践总结

  1. 适用场景判断

    • 当操作比元素类型更易变时优先选用
    • 当需要跨不相关类层次执行操作时使用
  2. 设计权衡

    • 优势:符合开闭原则,集中相关操作
    • 代价:增加系统复杂度,元素接口扩展困难
  3. 替代方案

    • 简单场景:考虑使用迭代器+策略模式组合
    • 功能扩展:AOP(面向切面编程)
  4. 架构集成

    • 框架设计:作为扩展点机制
    • 领域驱动设计:分离领域模型与技术实现

访问者模式在复杂业务系统中能显著提升架构的扩展性和可维护性,但需谨慎评估其对系统复杂度的增加。在编译器设计、复杂报表系统等场景中表现尤为出色,是系统架构师解决操作扩展问题的有力工具。
19. 模板方法

模板方法模式详解(系统架构师视角)

模式定义

模板方法模式是一种行为设计模式,它在抽象类中定义算法的骨架,将某些步骤延迟到子类实现。该模式通过固定算法结构确保核心流程不变,同时允许子类重写特定步骤的实现。

核心结构
// Java示例
abstract class AbstractClass {
    // 模板方法(final防止子类覆盖算法结构)
    public final void templateMethod() {
        step1();
        step2();  // 抽象步骤
        step3();
        if (hook()) {  // 钩子方法
            step4();
        }
    }

    // 固定步骤(可提供默认实现)
    private void step1() {
        System.out.println("固定步骤1");
    }

    // 抽象步骤(子类必须实现)
    protected abstract void step2();

    // 可选步骤(子类可覆盖)
    protected void step3() {
        System.out.println("默认步骤3");
    }

    // 钩子方法(控制流程扩展点)
    protected boolean hook() {
        return true;
    }
}
// C#示例
abstract class AbstractClass {
    public void TemplateMethod() {
        Step1();
        Step2();  // 抽象步骤
        Step3();
        if (Hook()) {  // 钩子方法
            Step4();
        }
    }

    private void Step1() => Console.WriteLine("固定步骤1");
    protected abstract void Step2();
    protected virtual void Step3() => Console.WriteLine("默认步骤3");
    protected virtual bool Hook() => true;
}
典型应用场景
  1. 框架扩展点设计

    • 场景:开发框架时固定核心流程(如Spring的事务管理、Servlet生命周期)
    • 示例:
      // Java Servlet
      public abstract class HttpServlet {
          protected void service(HttpServletRequest req, HttpServletResponse resp) {
              // 固定流程
              if (req.getMethod().equals("GET")) doGet(...);
              else if (req.getMethod().equals("POST")) doPost(...);
          }
          protected abstract void doGet(...); // 子类实现
      }
      
  2. 跨平台业务逻辑

    • 场景:多平台实现相同流程但细节不同(如支付流程:验证→执行→日志)
    • 示例:
      // C#支付处理
      abstract class PaymentProcessor {
          public void Process() {
              Validate();
              ExecutePayment(); // 平台相关实现
              LogResult();
          }
          protected abstract void ExecutePayment();
      }
      
  3. 算法扩展

    • 场景:算法结构固定但部分步骤可变(如数据解析:读数据→解析→输出)
    • 示例:Java集合框架的AbstractList定义骨架方法,子类实现get()
  4. 生命周期管理

    • 场景:对象创建/初始化的固定流程(如游戏角色生成:加载资源→初始化状态→注册事件)
      abstract class GameCharacter {
          public final void init() {
              loadModel();
              initAI();  // 子类自定义AI逻辑
              registerEvents();
          }
          protected abstract void initAI();
      }
      
架构注意事项
  1. 流程控制

    • 保护模板方法:用final(Java)/sealed(C#)修饰模板方法防止子类破坏结构
    • ⚠️ 避免过度拆分:抽象步骤不宜过多(通常3-5个),否则增加子类实现负担
  2. 扩展性设计

    • 钩子方法:提供带默认实现的虚方法(如hook()),允许子类影响主流程
    • 好莱坞原则:“Don’t call us, we’ll call you” – 子类不应直接调用父类
  3. 继承风险

    • 里氏替换原则:子类扩展时不得改变父类既定行为
    • ⚠️ 组合替代:若存在多重变化维度,考虑结合策略模式
架构最佳实践
  1. 层次化抽象

    AbstractClass
    +templateMethod()
    +step2()
    ConcreteClassA
    +step2()
    ConcreteClassB
    +step2()
  2. 文档规范

    • 明确标注抽象方法的契约(前置/后置条件)
    • 示例:Java注释
      /**
       * 实现支付执行逻辑(必须保证幂等性)
       * @throws PaymentException 超过重试次数时抛出
       */
      protected abstract void executePayment();
      
  3. 防御式编程

    • 在模板方法中添加关键检查:
      public void TemplateMethod() {
          if (!IsValidState()) throw new InvalidOperationException();
          // ...继续流程
      }
      
  4. 与其它模式协作

    • 工厂方法模式:在模板方法中调用工厂方法创建对象
    • 策略模式:将可变步骤委托给策略接口,避免继承膨胀
反模式警示
  1. 流程碎片化
    ❌ 错误:将算法拆分成过多细碎步骤
    ✅ 改进:合并相关步骤,保持高内聚

  2. 子类耦合父类
    ❌ 错误:子类方法直接调用父类具体方法
    ✅ 改进:通过抽象方法隔离依赖

  3. 过度使用继承

    graph LR
      A[模板方法模式] --> B{是否需要支持运行时变更行为?}
      B -->|是| C[改用策略模式]
      B -->|否| D[继续使用模板方法]
    
性能考量
  • 虚方法调用成本:在高性能场景(如金融交易),避免深层继承树
  • 解决方案:C#使用sealed修饰叶子子类,Java启用JIT内联优化

架构师决策点:当系统需要 强制统一流程 且存在 可扩展步骤 时优先选用模板方法模式,在框架设计和跨平台实现中尤为有效。同时需警惕"继承地狱",必要时结合组合模式优化结构。

  1. 解释器

解释器模式详解

模式定义

解释器模式(Interpreter Pattern) 是一种行为设计模式,用于定义语言的文法规则,并构建解释器来解释语言中的表达式。它将语法解析分解为多个小类,通过组合这些类实现语法解释功能。

核心组件
组件 说明
AbstractExpression 抽象表达式接口,声明解释操作(如 Interpret()
TerminalExpression 终结符表达式,实现与文法中终结符相关的解释(如变量、常量)
NonterminalExpression 非终结符表达式,通过组合子表达式解释复杂语法(如运算符、逻辑规则)
Context 全局上下文信息(如变量存储、函数表)
Client 构建语法树并触发解释操作

C# / Java 代码实现

场景示例:SQL WHERE 条件解析

假设需要解析类似 "Age > 25 AND Country = 'USA'" 的条件表达式。

C# 实现
// 抽象表达式
public interface IExpression {
    bool Interpret(Dictionary<string, object> context);
}

// 终结符表达式:变量
public class VariableExpression : IExpression {
    private string _key;
    public VariableExpression(string key) => _key = key;
    public bool Interpret(Dictionary<string, object> context) 
        => context.ContainsKey(_key);
}

// 终结符表达式:常量
public class ConstantExpression : IExpression {
    private object _value;
    public ConstantExpression(object value) => _value = value;
    public bool Interpret(Dictionary<string, object> context) 
        => _value != null;
}

// 非终结符表达式:等于操作
public class EqualsExpression : IExpression {
    private IExpression _left, _right;
    public EqualsExpression(IExpression left, IExpression right) 
        => (_left, _right) = (left, right);
    
    public bool Interpret(Dictionary<string, object> context) {
        dynamic leftVal = context[(_left as VariableExpression)?._key ?? ""];
        dynamic rightVal = (_right as ConstantExpression)?._value;
        return leftVal == rightVal;
    }
}

// 非终结符表达式:AND 操作
public class AndExpression : IExpression {
    private IExpression _expr1, _expr2;
    public AndExpression(IExpression expr1, IExpression expr2) 
        => (_expr1, _expr2) = (expr1, expr2);
    
    public bool Interpret(Dictionary<string, object> context) 
        => _expr1.Interpret(context) && _expr2.Interpret(context);
}

// 客户端调用
var context = new Dictionary<string, object> {
    { "Age", 30 }, 
    { "Country", "USA" }
};

var expr = new AndExpression(
    new GreaterThanExpression(
        new VariableExpression("Age"),
        new ConstantExpression(25)
    ),
    new EqualsExpression(
        new VariableExpression("Country"),
        new ConstantExpression("USA")
    )
);

Console.WriteLine(expr.Interpret(context)); // 输出: True
Java 实现
// 抽象表达式
interface Expression {
    boolean interpret(Map<String, Object> context);
}

// 终结符:变量
class VariableExpression implements Expression {
    private String key;
    public VariableExpression(String key) { this.key = key; }
    public boolean interpret(Map<String, Object> context) {
        return context.containsKey(key);
    }
}

// 终结符:常量
class ConstantExpression implements Expression {
    private Object value;
    public ConstantExpression(Object value) { this.value = value; }
    public boolean interpret(Map<String, Object> context) {
        return value != null;
    }
}

// 非终结符:等于操作
class EqualsExpression implements Expression {
    private Expression left, right;
    public EqualsExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    public boolean interpret(Map<String, Object> context) {
        Object leftVal = context.get(((VariableExpression) left).key);
        Object rightVal = ((ConstantExpression) right).value;
        return leftVal.equals(rightVal);
    }
}

// 客户端
Map<String, Object> context = new HashMap<>();
context.put("Age", 30);
context.put("Country", "USA");

Expression expr = new AndExpression(
    new GreaterThanExpression(
        new VariableExpression("Age"),
        new ConstantExpression(25)
    ),
    new EqualsExpression(
        new VariableExpression("Country"),
        new ConstantExpression("USA"))
);

System.out.println(expr.interpret(context)); // 输出: true

常用应用场景

  1. 领域特定语言(DSL)
    • 规则引擎(如Drools)
    • 业务规则配置(如折扣规则、风控规则)
  2. 语法解析
    • SQL WHERE 条件解析
    • 数学公式计算器
  3. 配置文件解析
    • 自定义格式的配置规则
    • 游戏脚本系统
  4. 正则表达式引擎
    • 模式匹配解释器

注意事项与架构建议

⚠️ 注意事项
  1. 性能问题
    • 深层嵌套语法树会降低性能(考虑缓存解释结果)
    • 避免在性能敏感场景使用(如高频交易)
  2. 文法复杂度
    • 仅适合简单文法(BNF范式可描述)
    • 复杂文法需用解析器生成器(如ANTLR)
  3. 维护成本
    • 每增加一条规则需新增类
    • 过度使用会导致类膨胀
🏗️ 架构建议
  1. 结合组合模式
    • 用树形结构组织表达式(如 CompositeExpression
  2. 分离解析与执行
    • 使用单独解析器构建语法树
    • 解释器仅负责执行
  3. 上下文优化
    • 线程安全的上下文设计
    • 预编译常用表达式(如预计算常量)
  4. 扩展性设计
    // 通过装饰器增加新功能
    public class CachedExpression : IExpression {
        private IExpression _expr;
        private bool? _lastResult;
        public bool Interpret(Dictionary<string, object> context) {
            return _lastResult ??= _expr.Interpret(context);
        }
    }
    
  5. 替代方案
    • 复杂场景用访问者模式遍历语法树
    • 考虑现成工具(如Roslyn、Eclipse JDT)

总结

适用场景

  • 需要灵活扩展语法规则
  • 文法简单且执行频率不高
  • 避免重复解析相同逻辑(如模板引擎)

规避场景

  • 高性能需求系统
  • 文法规则频繁变化
  • 复杂语法(如完整编程语言)

通过合理设计,解释器模式能高效解决特定领域语言解析问题,但需警惕其潜在复杂性和性能瓶颈。在实际架构中,优先评估是否可用现成解析库替代自定义实现。
21. 享元

享元模式(Flyweight Pattern)详解

模式定义

享元模式是一种结构型设计模式,通过共享大量细粒度对象来减少内存占用和提高性能。核心思想是将对象状态分为:

  • 内部状态(Intrinsic):可共享的、不变的部分(如字符编码)
  • 外部状态(Extrinsic):不可共享的、变化的部分(如位置坐标)
模式结构
创建/管理
请求
设置外部状态
FlyweightFactory
-flyweights: Map
+GetFlyweight(key)
Flyweight
+Operation(extrinsicState)
ConcreteFlyweight
-intrinsicState
+Operation(extrinsicState)
UnsharedFlyweight
-allState
+Operation(extrinsicState)
Client
-extrinsicState
C# 实现示例
// 抽象享元
public interface ITextCharacter {
    void Display(int position);
}

// 具体享元(包含内部状态)
public class Character : ITextCharacter {
    private readonly char _symbol; // 内部状态
    
    public Character(char symbol) => _symbol = symbol;
    
    public void Display(int position) => 
        Console.WriteLine($"Symbol: {_symbol}, Position: {position}");
}

// 享元工厂
public class CharacterFactory {
    private readonly Dictionary<char, ITextCharacter> _characters = new();
    
    public ITextCharacter GetCharacter(char key) {
        if (!_characters.TryGetValue(key, out var character)) {
            character = new Character(key);
            _characters.Add(key, character);
        }
        return character;
    }
}

// 客户端
var factory = new CharacterFactory();
var charA = factory.GetCharacter('A');
charA.Display(10); // 外部状态:位置
Java 实现示例
// 抽象享元
interface TextCharacter {
    void display(int position);
}

// 具体享元
class Character implements TextCharacter {
    private final char symbol; // 内部状态
    
    public Character(char symbol) { this.symbol = symbol; }
    
    @Override
    public void display(int position) {
        System.out.println("Symbol: " + symbol + ", Position: " + position);
    }
}

// 享元工厂
class CharacterFactory {
    private final Map<Character, TextCharacter> pool = new HashMap<>();
    
    public TextCharacter getCharacter(char key) {
        return pool.computeIfAbsent(key, Character::new);
    }
}

// 客户端
CharacterFactory factory = new CharacterFactory();
TextCharacter charA = factory.getCharacter('A');
charA.display(10);

常用场景

  1. 文本编辑器

    • 共享字符对象(内部状态:字体、大小)
    • 外部状态:位置、颜色
  2. 游戏开发

    • 共享粒子/树木/武器对象(内部状态:纹理、模型)
    • 外部状态:位置、旋转角度
  3. 图形处理

    • 共享图形对象(内部状态:形状类型)
    • 外部状态:坐标、缩放比例
  4. 数据库连接池

    • 共享连接对象(内部状态:配置)
    • 外部状态:会话状态
  5. UI组件库

    • 共享按钮/图标(内部状态:样式)
    • 外部状态:位置、点击事件

注意事项

  1. 线程安全问题

    • 共享对象需设计为不可变(Immutable)
    • 使用线程安全容器(如 ConcurrentDictionary
  2. 外部状态管理

    • 客户端负责维护外部状态
    • 避免外部状态污染内部状态
  3. 性能权衡

    • 对象共享会引入查找开销(工厂模式)
    • 适用于对象创建成本高且数量大的场景
  4. 内存泄漏风险

    • 长期持有未使用的享元对象
    • 解决方案:弱引用(WeakReference)或定期清理

架构建议

  1. 结合工厂模式

    • 强制通过工厂获取对象,确保共享机制
  2. 与组合模式结合

    • 处理树形结构时,共享叶子节点
    // 组合模式示例
    public class TreeNode : IComponent {
        private readonly ITextCharacter _character;
        private readonly List<IComponent> _children = new();
        
        public void Add(IComponent comp) => _children.Add(comp);
        public void Render(int x) {
            _character.Display(x);
            foreach (var child in _children) child.Render(x + 10);
        }
    }
    
  3. 外部状态存储优化

    • 使用轻量结构存储外部状态(如元组、结构体)
    • 避免外部状态包含大对象
  4. 性能监控

    • 跟踪享元对象命中率(Hit Rate)
    • 当命中率<70%时,考虑是否滥用模式
  5. 区分共享边界

    • 明确划分线程级共享/进程级共享
    • 分布式场景使用享元代理(Flyweight Proxy)

经典案例:游戏地图渲染

// 地形类型(内部状态)
enum TerrainType { FOREST, MOUNTAIN, WATER }

// 享元对象
class Terrain {
    private final TerrainType type;
    private final String texture; // 大纹理数据(共享)
    
    public Terrain(TerrainType type, String texture) { ... }
    
    public void render(int x, int y) {
        // 使用外部状态(x,y)渲染
    }
}

// 客户端使用
Terrain forest = factory.getTerrain(TerrainType.FOREST);
for (int i=0; i<1000; i++) {
    forest.render(randomX(), randomY()); // 外部状态
}

节省效果:1,000,000个地形成分 → 仅需3个享元对象


反模式警示

  1. 强行共享

    • 对象差异过大时,维护成本高于内存节省
  2. 忽略外部状态成本

    • 频繁计算外部状态导致CPU开销剧增
  3. 过度设计

    • 小规模对象池(<1000实例)无需享元模式

性能优化技巧

  1. 懒加载 + 预加载结合

    public class OptimizedFactory {
        private ConcurrentDictionary<char, Lazy<ITextCharacter>> _pool 
            = new ConcurrentDictionary<>();
        
        public ITextCharacter GetChar(char key) {
            return _pool.GetOrAdd(key, 
                k => new Lazy<ITextCharacter>(() => new Character(k))
            ).Value;
        }
    }
    
  2. 使用值对象(Value Object)

    • C# 中 readonly struct / Java 中 record
    • 确保内部状态不可变
  3. 分级存储策略

    强引用
    弱引用
    序列化
    高频对象
    内存缓存
    低频对象
    二级缓存
    历史对象
    磁盘存储

总结

适用场景:存在大量重复对象、对象状态可分拆、内存压力显著
规避场景:对象差异性大、外部状态维护成本高、系统规模小
最佳实践

  • 严格区分内部/外部状态
  • 工厂类添加内存监控钩子
  • 与对象池模式结合处理非共享对象
  • 在游戏引擎、文档处理器等重资源场景优先采用
  1. 代理

代理模式详解

核心概念

代理模式是一种结构型设计模式,通过创建代理对象控制对目标对象的访问。代理在客户端和目标对象之间充当中介,提供额外的逻辑层(如访问控制、延迟加载、日志记录等),遵循开闭原则

三种角色
  1. Subject(抽象主题)
    定义目标对象和代理的公共接口
  2. RealSubject(真实主题)
    实际执行业务逻辑的目标对象
  3. Proxy(代理)
    持有真实主题的引用,控制访问并添加增强功能

应用场景与代码示例

1. 虚拟代理(延迟加载)

场景:初始化开销大的对象(如图片/文件加载)

// C# 示例
public interface IImage { void Display(); }

public class HighResImage : IImage {
    public HighResImage(string path) => LoadImage(path); // 高开销操作
    public void Display() => Console.WriteLine("显示高清图片");
}

public class ImageProxy : IImage {
    private string _path;
    private HighResImage _realImage;
    
    public void Display() {
        _realImage ??= new HighResImage(_path); // 延迟初始化
        _realImage.Display();
    }
}
// Java 示例
interface Image { void display(); }

class RealImage implements Image {
    public RealImage(String path) { loadFromDisk(path); }
    public void display() { System.out.println("显示图片"); }
}

class ProxyImage implements Image {
    private String path;
    private RealImage realImage;
    
    @Override
    public void display() {
        if (realImage == null) realImage = new RealImage(path);
        realImage.display();
    }
}
2. 保护代理(访问控制)

场景:敏感操作权限验证

// C# 示例
public interface IDatabase { void Query(string sql); }

public class RealDatabase : IDatabase {
    public void Query(string sql) => Console.WriteLine($"执行: {sql}");
}

public class AuthProxy : IDatabase {
    private RealDatabase _db = new();
    private string _userRole;
    
    public void Query(string sql) {
        if (_userRole == "Admin") _db.Query(sql);
        else throw new UnauthorizedAccessException("权限不足");
    }
}
3. 远程代理(网络通信)

场景:分布式系统跨进程调用(Java RMI 示例)

// Java RMI 接口
public interface RemoteService extends Remote {
    String process() throws RemoteException;
}

// 客户端调用
Registry registry = LocateRegistry.getRegistry("host", 1099);
RemoteService service = (RemoteService) registry.lookup("ServiceName");
service.process(); // 代理处理网络通信
4. 日志记录代理

场景:审计关键操作

// C# 日志代理
public class LoggingProxy : IDatabase {
    private IDatabase _target;
    public void Query(string sql) {
        Log($"执行SQL: {sql} 时间: {DateTime.Now}");
        _target.Query(sql);
    }
}

架构建议与注意事项

最佳实践
  1. 接口一致性原则

    实现
    实现
    Client
    Subject
    RealSubject
    Proxy

    确保代理与真实主题实现相同接口

  2. 动态代理优先

    • Java: 使用 java.lang.reflect.Proxy
    • C#: 使用 DispatchProxy 或第三方库(如 Castle DynamicProxy)
    // Java 动态代理示例
    InvocationHandler handler = (proxy, method, args) -> {
        System.out.println("前置处理");
        return method.invoke(target, args);
    };
    Subject proxy = (Subject) Proxy.newProxyInstance(
        loader, new Class[]{Subject.class}, handler);
    
  3. 代理链组合
    通过责任链模式组合多个代理:

    客户端 -> [日志代理] -> [缓存代理] -> [真实对象]
    
注意事项
  1. 性能影响

    • 避免多层嵌套代理(特别是远程代理)
    • 高频调用场景慎用
  2. 初始化陷阱
    虚拟代理需注意线程安全问题:

    // C# 线程安全延迟初始化
    private Lazy<RealSubject> _subject = new Lazy<RealSubject>(
        () => new RealSubject(), LazyThreadSafetyMode.ExecutionAndPublication);
    
  3. 循环依赖
    代理与真实对象避免相互引用

  4. 异常处理
    远程代理需处理网络异常:

    try {
        remoteService.process();
    } catch (RemoteException e) {
        logger.error("网络调用失败", e);
    }
    
典型应用框架
框架 代理类型 作用
Spring AOP JDK动态代理 切面编程
Entity Framework 延迟加载代理 按需加载关联数据
WCF 服务代理 远程服务调用
Hibernate 字节码增强 属性延迟加载

总结

代理模式适用场景

  • 需要控制对象访问(权限/生命周期)
  • 添加与核心逻辑无关的横切关注点(日志/监控)
  • 优化资源使用(延迟加载/缓存)
  • 简化复杂系统访问(远程调用)

替代方案

  • 装饰器模式:侧重功能增强而非访问控制
  • 外观模式:封装子系统接口,不控制单个对象

模式选择速查表

问题类型 推荐模式
全局访问点 单例模式
灵活创建对象 工厂方法/抽象工厂
分步构建复杂对象 建造者模式
接口不兼容 适配器模式
多维度扩展 桥接模式
树形结构处理 组合模式
动态添加功能 装饰器模式
简化复杂系统 外观模式
状态驱动行为 状态模式
算法自由切换 策略模式
事件通知机制 观察者模式
操作封装 命令模式

黄金法则

  1. 优先组合而非继承
  2. 面向接口编程
  3. 高内聚低耦合
  4. 对修改关闭,对扩展开放(开闭原则)

实际案例:电商系统典型模式组合

  • 支付模块:策略模式+工厂方法
  • 订单管理:状态模式+观察者模式
  • 商品展示:装饰器模式(价格修饰)
  • 权限控制:代理模式
  • 日志系统:责任链模式+适配器模式

网站公告

今日签到

点亮在社区的每一天
去签到