行为型模式(协作的艺术)
  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) { ... }
      }
      
    • Java:java.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日志级别过滤链
NettyChannelHandler处理链

责任链模式通过解耦请求发送者和处理者,显著提升系统扩展性。适用于需动态调整处理流程的场景,但需谨慎处理链的终止条件和性能影响。
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 AOPJDK动态代理切面编程
Entity Framework延迟加载代理按需加载关联数据
WCF服务代理远程服务调用
Hibernate字节码增强属性延迟加载

总结

代理模式适用场景:

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

替代方案:

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

模式选择速查表

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

黄金法则:

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

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

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

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐