行为型模式

111 阅读8分钟

行为型模式通过责任链传递请求、命令封装操作、策略切换算法、观察者通知状态变化及模板方法定义骨架等,解耦对象交互,动态分配职责,提升系统灵活性和扩展性,适用于算法、通信与流程管理场景。


1. 责任链模式(Chain of Responsibility)

定义

多个对象依次处理请求,直到有对象处理它为止。

类图

┌───────────────────┐       ┌───────────────────┐
│ Handler           │<>─────│ Handler           │
├───────────────────┤       ├───────────────────┤
│ +nextHandler      │       │ +setNext()        │
│ +handleRequest()  │       │ +handleRequest()  │
└─────────┬─────────┘       └─────────┬─────────┘
          △                           △
          │                           │
┌───────────────────┐       ┌───────────────────┐
│ ConcreteHandlerA  │       │ ConcreteHandlerB  │
├───────────────────┤       ├───────────────────┤
│ +handleRequest()  │       │ +handleRequest()  │
└───────────────────┘       └───────────────────┘

Java 实现

// 抽象处理者
abstract class Handler {
    protected Handler next;
​
    public void setNext(Handler next) {
        this.next = next;
    }
​
    public abstract void handleRequest(int request);
}
​
// 具体处理者A
class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request <= 10) {
            System.out.println("HandlerA 处理请求: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}
​
// 具体处理者B
class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request > 10 && request <= 20) {
            System.out.println("HandlerB 处理请求: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        Handler chain = new ConcreteHandlerA();
        chain.setNext(new ConcreteHandlerB());
​
        chain.handleRequest(5);  // HandlerA处理
        chain.handleRequest(15); // HandlerB处理
        chain.handleRequest(25); // 无处理
    }
}

适用场景

  • HTTP 请求过滤器链
  • 审批流程(如报销多级审批)

优缺点

  • 优点:解耦请求发送者和接收者,动态调整责任链。
  • 缺点:请求可能未被处理,调试较复杂。

2. 命令模式(Command)

定义

将请求封装为对象,支持请求的排队、撤销和日志记录。

类图

┌───────────────────┐       ┌───────────────────┐
│ Command           │       │ Invoker           │
├───────────────────┤       ├───────────────────┤
│ +execute()        │       │ +setCommand()     │
│ +undo()           │       │ +executeCommand() │
└──────┬────────────┘       └───────────────────┘
       △
       │
┌───────────────────┐
│ ConcreteCommand   │
├───────────────────┤
│ -receiver         │
│ +execute()        │
└──────┬────────────┘
       △
       │
┌───────────────────┐
│ Receiver          │
├───────────────────┤
│ +action()         │
└───────────────────┘

Java 实现

// 接收者(实际执行操作)
class Light {
    public void turnOn() { System.out.println("灯已打开"); }
    public void turnOff() { System.out.println("灯已关闭"); }
}
​
// 抽象命令
interface Command {
    void execute();
    void undo();
}
​
// 具体命令
class TurnOnCommand implements Command {
    private Light light;
    public TurnOnCommand(Light light) { this.light = light; }
    @Override
    public void execute() { light.turnOn(); }
    @Override
    public void undo() { light.turnOff(); }
}
​
// 调用者(触发命令)
class RemoteControl {
    private Command command;
    public void setCommand(Command command) { this.command = command; }
    public void pressButton() { command.execute(); }
    public void pressUndo() { command.undo(); }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        Light light = new Light();
        Command cmd = new TurnOnCommand(light);
        RemoteControl remote = new RemoteControl();
        remote.setCommand(cmd);
        
        remote.pressButton();  // 输出: 灯已打开
        remote.pressUndo();   // 输出: 灯已关闭
    }
}

适用场景

  • GUI 按钮操作封装
  • 事务回滚、操作历史记录

优缺点

  • 优点:解耦操作调用者和执行者,支持扩展。
  • 缺点:每个命令需单独实现类,代码量大。

3. 解释器模式(Interpreter)

定义

为特定语法规则定义解释器,用于解析表达式。

类图

┌───────────────────┐       ┌───────────────────┐
│ AbstractExpression│<>─────│ TerminalExpression│
├───────────────────┤       ├───────────────────┤
│ +interpret()      │       │ +interpret()      │
└─────────┬─────────┘       └───────────────────┘
          △
          │
┌───────────────────┐
│ NonTerminalExpression │
├───────────────────┤
│ +interpret()      │
└───────────────────┘

Java 实现

// 抽象表达式
interface Expression {
    boolean interpret(String context);
}
​
// 终结符表达式
class TerminalExpression implements Expression {
    private String data;
    public TerminalExpression(String data) { this.data = data; }
    @Override
    public boolean interpret(String context) {
        return context.contains(data);
    }
}
​
// 非终结符表达式(AND逻辑)
class AndExpression implements Expression {
    private Expression expr1;
    private Expression expr2;
    public AndExpression(Expression e1, Expression e2) {
        this.expr1 = e1;
        this.expr2 = e2;
    }
    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) && expr2.interpret(context);
    }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        Expression john = new TerminalExpression("John");
        Expression married = new TerminalExpression("Married");
        Expression isMarriedJohn = new AndExpression(john, married);
        
        System.out.println(isMarriedJohn.interpret("John Married")); // true
    }
}

适用场景

  • SQL 解析、正则表达式引擎
  • 数学公式计算器

优缺点

  • 优点:易于扩展新语法规则。
  • 缺点:复杂语法会导致类数量爆炸。

4. 迭代器模式(Iterator)

定义

提供一种顺序访问集合元素的方法,无需暴露内部结构。

类图

┌───────────────────┐       ┌───────────────────┐
│ Aggregate         │<>─────│ Iterator          │
├───────────────────┤       ├───────────────────┤
│ +createIterator() │       │ +hasNext()        │
└───────────────────┘       │ +next()           │
       △                     └─────────┬─────────┘
       │                               △
       │                               │
┌───────────────────┐       ┌───────────────────┐
│ ConcreteAggregate │       │ ConcreteIterator  │
├───────────────────┤       ├───────────────────┤
│ +createIterator() │       │ +hasNext()        │
└───────────────────┘       │ +next()           │
                            └───────────────────┘

Java 实现

// 自定义集合接口
interface MyCollection<T> {
    MyIterator<T> createIterator();
}
​
// 具体集合
class MyList<T> implements MyCollection<T> {
    private List<T> items = new ArrayList<>();
    public void add(T item) { items.add(item); }
    @Override
    public MyIterator<T> createIterator() {
        return new MyListIterator<>(items);
    }
}
​
// 迭代器接口
interface MyIterator<T> {
    boolean hasNext();
    T next();
}
​
// 具体迭代器
class MyListIterator<T> implements MyIterator<T> {
    private List<T> items;
    private int index = 0;
    public MyListIterator(List<T> items) { this.items = items; }
    @Override
    public boolean hasNext() { return index < items.size(); }
    @Override
    public T next() { return items.get(index++); }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        MyList<String> list = new MyList<>();
        list.add("A");
        list.add("B");
        
        MyIterator<String> it = list.createIterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

适用场景

  • Java 集合框架的 Iterator
  • 遍历复杂数据结构(树、图)

优缺点

  • 优点:隐藏集合内部实现,支持多种遍历方式。
  • 缺点:增加类的数量。

5. 中介者模式(Mediator)

定义

通过中介者对象减少对象间的直接耦合。

类图

┌───────────────────┐       ┌───────────────────┐
│ Mediator          │       │ Colleague         │
├───────────────────┤       ├───────────────────┤
│ +notify()         │       │ -mediator         │
└──────┬────────────┘       │ +send()           │
       △                     └─────────┬─────────┘
       │                               △
       │                               │
┌───────────────────┐       ┌───────────────────┐
│ ConcreteMediator  │       │ ConcreteColleague │
├───────────────────┤       ├───────────────────┤
│ +notify()         │       │ +send()           │
└───────────────────┘       └───────────────────┘

Java 实现

// 中介者接口
interface ChatMediator {
    void sendMessage(String msg, User user);
    void addUser(User user);
}
​
// 具体中介者(聊天室)
class ChatRoom implements ChatMediator {
    private List<User> users = new ArrayList<>();
    @Override
    public void addUser(User user) { users.add(user); }
    @Override
    public void sendMessage(String msg, User sender) {
        for (User u : users) {
            if (u != sender) u.receive(msg);
        }
    }
}
​
// 同事类(用户)
abstract class User {
    protected ChatMediator mediator;
    protected String name;
    public User(ChatMediator m, String name) {
        this.mediator = m;
        this.name = name;
    }
    public abstract void send(String msg);
    public void receive(String msg) {
        System.out.println(name + " 收到消息: " + msg);
    }
}
​
// 具体同事类
class ChatUser extends User {
    public ChatUser(ChatMediator m, String name) { super(m, name); }
    @Override
    public void send(String msg) {
        System.out.println(name + " 发送消息: " + msg);
        mediator.sendMessage(msg, this);
    }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        ChatMediator mediator = new ChatRoom();
        User alice = new ChatUser(mediator, "Alice");
        User bob = new ChatUser(mediator, "Bob");
        mediator.addUser(alice);
        mediator.addUser(bob);
        
        alice.send("Hello!"); // Bob收到消息
    }
}

适用场景

  • 聊天室、事件调度系统
  • 减少对象间网状依赖关系

优缺点

  • 优点:集中控制交互逻辑,降低耦合。
  • 缺点:中介者可能变得臃肿。

6. 备忘录模式(Memento)

定义

保存对象状态以便后续恢复。

类图

┌───────────────────┐       ┌───────────────────┐
│ Originator        │       │ Memento           │
├───────────────────┤       ├───────────────────┤
│ +createMemento()  │       │ -state            │
│ +restore()        │       └───────────────────┘
└──────┬────────────┘                 △
       │                               │
       │                       ┌───────┴───────┐
       │                       │ Caretaker     │
       │                       ├───────────────┤
       └───────────────────────│ -mementos     │
                               └───────────────┘

Java 实现

// 发起人(需要保存状态的对象)
class Editor {
    private String content;
    public void write(String content) { this.content = content; }
    public String getContent() { return content; }
    public EditorMemento save() { return new EditorMemento(content); }
    public void restore(EditorMemento memento) { content = memento.getContent(); }
}
​
// 备忘录(保存状态)
class EditorMemento {
    private final String content;
    public EditorMemento(String content) { this.content = content; }
    public String getContent() { return content; }
}
​
// 管理者(保存备忘录历史)
class History {
    private List<EditorMemento> mementos = new ArrayList<>();
    public void push(EditorMemento m) { mementos.add(m); }
    public EditorMemento pop() { return mementos.remove(mementos.size() - 1); }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        Editor editor = new Editor();
        History history = new History();
        
        editor.write("Version 1");
        history.push(editor.save());
        editor.write("Version 2");
        editor.restore(history.pop()); // 回退到Version 1
    }
}

适用场景

  • 文本编辑器撤销操作
  • 游戏存档/读档

优缺点

  • 优点:状态保存与恢复解耦。
  • 缺点:频繁保存可能占用内存。

7. 观察者模式(Observer)

定义

定义对象间的一对多依赖,状态变化时通知所有依赖者。

类图

┌───────────────────┐       ┌───────────────────┐
│ Subject           │<>─────│ Observer          │
├───────────────────┤       ├───────────────────┤
│ +attach()         │       │ +update()         │
│ +detach()         │       └───────────────────┘
│ +notify()         │                 △
└──────┬────────────┘                 │
       △                              │
       │                              │
┌───────────────────┐       ┌───────────────────┐
│ ConcreteSubject   │       │ ConcreteObserver  │
├───────────────────┤       ├───────────────────┤
│ +getState()       │       │ +update()         │
└───────────────────┘       └───────────────────┘

Java 实现

// 主题接口
interface Subject {
    void attach(Observer o);
    void detach(Observer o);
    void notifyObservers();
}
​
// 具体主题(温度传感器)
class TemperatureSensor implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private float temperature;
    
    public void setTemperature(float temp) {
        this.temperature = temp;
        notifyObservers();
    }
    
    @Override
    public void attach(Observer o) { observers.add(o); }
    @Override
    public void detach(Observer o) { observers.remove(o); }
    @Override
    public void notifyObservers() {
        for (Observer o : observers) o.update(temperature);
    }
}
​
// 观察者接口
interface Observer {
    void update(float temperature);
}
​
// 具体观察者(显示屏)
class Display implements Observer {
    @Override
    public void update(float temperature) {
        System.out.println("当前温度: " + temperature);
    }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        TemperatureSensor sensor = new TemperatureSensor();
        Display display = new Display();
        sensor.attach(display);
        sensor.setTemperature(25.5f); // 触发通知
    }
}

适用场景

  • 事件驱动系统(如 GUI 按钮点击)
  • 实时数据监控

优缺点

  • 优点:支持松耦合通信。
  • 缺点:观察者可能收到不相关通知。

8. 状态模式(State)

定义

允许对象在其内部状态改变时改变行为。

类图

┌───────────────────┐       ┌───────────────────┐
│ Context           │<>─────│ State             │
├───────────────────┤       ├───────────────────┤
│ +request()        │       │ +handle()         │
└──────┬────────────┘       └─────────┬─────────┘
       △                              △
       │                              │
┌───────────────────┐       ┌───────────────────┐
│ ConcreteStateA    │       │ ConcreteStateB    │
├───────────────────┤       ├───────────────────┤
│ +handle()         │       │ +handle()         │
└───────────────────┘       └───────────────────┘

Java 实现

// 状态接口
interface OrderState {
    void handle(OrderContext context);
}
​
// 具体状态:已下单
class OrderedState implements OrderState {
    @Override
    public void handle(OrderContext context) {
        System.out.println("订单

8. 策略模式(Strategy)

定义

定义一组算法族,封装每个算法,并使它们可以互相替换,让算法的变化独立于客户端。

类图

复制

┌───────────────────┐       ┌───────────────────┐
│ Strategy          │<>─────│ Context           │
├───────────────────┤       ├───────────────────┤
│ +execute()        │       │ -strategy         │
└──────┬────────────┘       │ +setStrategy()    │
       △                     │ +executeStrategy()│
       │                     └───────────────────┘
┌───────────────────┐
│ ConcreteStrategyA │
├───────────────────┤
│ +execute()        │
└───────────────────┘

Java 实现

java

复制

// 策略接口
interface SortingStrategy {
    void sort(int[] data);
}
​
// 具体策略:快速排序
class QuickSort implements SortingStrategy {
    @Override
    public void sort(int[] data) {
        System.out.println("使用快速排序");
        // 具体排序实现
    }
}
​
// 具体策略:归并排序
class MergeSort implements SortingStrategy {
    @Override
    public void sort(int[] data) {
        System.out.println("使用归并排序");
        // 具体排序实现
    }
}
​
// 上下文类(封装策略)
class Sorter {
    private SortingStrategy strategy;
    
    public void setStrategy(SortingStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void executeSort(int[] data) {
        strategy.sort(data);
    }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        Sorter sorter = new Sorter();
        sorter.setStrategy(new QuickSort());
        sorter.executeSort(new int[]{5, 2, 9}); // 输出: 使用快速排序
    }
}

适用场景

  • 支付方式选择(支付宝、微信、信用卡等)
  • 动态切换算法(如排序、压缩算法)

优缺点

  • 优点:算法可扩展性强,符合开闭原则。
  • 缺点:策略类数量增加,客户端需理解不同策略差异。

10. 模板方法模式(Template Method)

定义

定义算法的骨架,将某些步骤延迟到子类中实现。

类图

复制

┌───────────────────┐
│ AbstractClass     │
├───────────────────┤
│ +templateMethod() │
│ +step1()          │
│ +step2()          │
└──────┬────────────┘
       △
       │
┌───────────────────┐
│ ConcreteClass     │
├───────────────────┤
│ +step1()          │
│ +step2()          │
└───────────────────┘

Java 实现

java

复制

// 抽象模板类
abstract class Beverage {
    // 模板方法(定义算法骨架)
    public final void prepare() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
    
    // 固定步骤(通用实现)
    private void boilWater() {
        System.out.println("烧水");
    }
    
    private void pourInCup() {
        System.out.println("倒入杯子");
    }
    
    // 抽象步骤(由子类实现)
    abstract void brew();
    abstract void addCondiments();
}
​
// 具体子类:咖啡
class Coffee extends Beverage {
    @Override
    void brew() {
        System.out.println("冲泡咖啡粉");
    }
    @Override
    void addCondiments() {
        System.out.println("加糖和牛奶");
    }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        coffee.prepare();
        // 输出顺序:烧水 → 冲泡咖啡粉 → 倒入杯子 → 加糖和牛奶
    }
}

适用场景

  • JDBC 模板(固定流程:连接 → 执行 → 关闭)
  • 工作流框架(如审批流程的固定步骤)

优缺点

  • 优点:代码复用,避免重复代码。
  • 缺点:算法骨架难以修改,可能限制灵活性。

11. 访问者模式(Visitor)

定义

在不修改类结构的前提下,为类添加新的操作。

类图

复制

┌───────────────────┐       ┌───────────────────┐
│ Visitor           │       │ Element           │
├───────────────────┤       ├───────────────────┤
│ +visitA()         │       │ +accept(Visitor)  │
│ +visitB()         │       └─────────┬─────────┘
└──────┬────────────┘                 △
       △                              │
       │                              │
┌───────────────────┐       ┌───────────────────┐
│ ConcreteVisitor   │       │ ConcreteElementA  │
├───────────────────┤       ├───────────────────┤
│ +visitA()         │       │ +accept(Visitor)  │
└───────────────────┘       └───────────────────┘

Java 实现

java

复制

// 元素接口
interface DocumentElement {
    void accept(Visitor visitor);
}
​
// 具体元素:文本段落
class TextElement implements DocumentElement {
    private String content;
    public TextElement(String content) { this.content = content; }
    public String getContent() { return content; }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
​
// 具体元素:图片
class ImageElement implements DocumentElement {
    private String url;
    public ImageElement(String url) { this.url = url; }
    public String getUrl() { return url; }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
​
// 访问者接口
interface Visitor {
    void visit(TextElement text);
    void visit(ImageElement image);
}
​
// 具体访问者:统计字数
class WordCountVisitor implements Visitor {
    private int wordCount = 0;
    @Override
    public void visit(TextElement text) {
        wordCount += text.getContent().split(" ").length;
    }
    @Override
    public void visit(ImageElement image) {
        // 图片不统计字数
    }
    public int getWordCount() { return wordCount; }
}
​
// 客户端调用
public class Client {
    public static void main(String[] args) {
        List<DocumentElement> elements = new ArrayList<>();
        elements.add(new TextElement("Hello World"));
        elements.add(new ImageElement("photo.jpg"));
        
        WordCountVisitor visitor = new WordCountVisitor();
        for (DocumentElement e : elements) {
            e.accept(visitor);
        }
        System.out.println("总字数: " + visitor.getWordCount()); // 输出: 总字数: 2
    }
}

适用场景

  • 编译器语法树分析(如类型检查、代码优化)
  • 复杂对象结构的统计或导出操作

优缺点

  • 优点:新增操作无需修改元素类,符合开闭原则。
  • 缺点:元素类结构需稳定,新增元素类型需修改所有访问者。