enyang
enyang
Published on 2025-11-22 / 2 Visits
0
0

设计模式 <4> —— 行为型模式 (Behavioral Patterns)

行为型设计模式关注对象之间的通信和责任分配,尤其是如何通过不同的方式使得对象间能够有效协作。这些模式描述了类和对象之间的交互模式,帮助解决在运行时如何灵活地分配责任、简化复杂的行为逻辑,并且增强代码的扩展性和可维护性。


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

责任链模式使得多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些处理对象串成一条链,并沿着链传递请求,直到有一个对象处理它为止。

实现方式

  • 定义一个处理请求的抽象类。

  • 每个具体处理者类实现该抽象类,并定义自己的处理逻辑。

  • 处理者对象通过链式传递请求。

Java实现

// 抽象处理者
abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(String request);
}

// 具体处理者A
class ConcreteHandlerA extends Handler {
    public void handleRequest(String request) {
        if (request.equals("A")) {
            System.out.println("Handler A is handling the request.");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 具体处理者B
class ConcreteHandlerB extends Handler {
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("Handler B is handling the request.");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        
        handlerA.setNextHandler(handlerB);

        handlerA.handleRequest("A");  // 输出: Handler A is handling the request.
        handlerA.handleRequest("B");  // 输出: Handler B is handling the request.
    }
}
  • 每个 Handler 可以根据请求的类型决定是否处理请求,或者将请求传递给下一个处理者。

  • 通过责任链模式,可以灵活地处理复杂的请求流程。


2. 命令模式 (Command Pattern)

命令模式将请求封装成对象,从而使得可以用不同的请求、队列或日志来参数化其他对象。命令模式能够解耦请求的发送者和接收者,使得请求的执行可以在不直接暴露接收者的情况下进行。

实现方式

  • 定义一个命令接口,声明执行请求的方法。

  • 每个具体命令类实现该接口,封装特定的请求。

  • 客户端通过调用命令对象的执行方法来触发操作。

Java实现

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

// 具体命令类
class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.turnOn();
    }
}

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

    public void turnOff() {
        System.out.println("Light is OFF");
    }
}

// 调用者类
class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

public class CommandDemo {
    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 is ON
    }
}
  • Command 接口封装了请求,LightOnCommand 是一个具体的命令对象,它调用 Light 类的方法。

  • 客户端通过 RemoteControl 发出命令,而不直接与 Light 类打交道。


3. 解释器模式 (Interpreter Pattern)

解释器模式提供了评估语言的方式。该模式主要用于设计一个解释器,用于解释某种语言或表达式的文法。该模式通常用于构建一些复杂的计算机语言解释器、编译器等。

实现方式

  • 定义一个表达式接口,所有的终结符和非终结符都实现这个接口。

  • 每个表达式类代表文法规则的一部分。

Java实现

// 抽象表达式
interface Expression {
    boolean interpret(String context);
}

// 终结符表达式
class TerminalExpression implements Expression {
    private String data;

    public TerminalExpression(String data) {
        this.data = data;
    }

    public boolean interpret(String context) {
        return context.contains(data);
    }
}

// 非终结符表达式
class OrExpression implements Expression {
    private Expression expr1;
    private Expression expr2;

    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    public boolean interpret(String context) {
        return expr1.interpret(context) || expr2.interpret(context);
    }
}

public class InterpreterDemo {
    public static void main(String[] args) {
        Expression isMale = new TerminalExpression("Male");
        Expression isMarried = new TerminalExpression("Married");

        Expression isMarriedMale = new OrExpression(isMale, isMarried);

        System.out.println("Is Male? " + isMale.interpret("Male"));  // 输出: true
        System.out.println("Is Married? " + isMarried.interpret("Single"));  // 输出: false
        System.out.println("Is Married Male? " + isMarriedMale.interpret("Married"));  // 输出: true
    }
}
  • TerminalExpression 是终结符,检查字符串是否包含某个词语。

  • OrExpression 是非终结符,它结合两个表达式,并根据逻辑判断来决定是否满足条件。


4. 迭代器模式 (Iterator Pattern)

迭代器模式提供了一种方法来顺序访问一个集合对象中的元素,而又不暴露该对象的内部表示。它允许你以一致的方式访问不同的数据结构中的元素。

实现方式

  • 定义一个迭代器接口,声明常见的操作方法。

  • 每个集合类都提供一个迭代器来遍历自己的元素。

Java实现

// 迭代器接口
interface Iterator {
    boolean hasNext();
    Object next();
}

// 集合接口
interface Container {
    Iterator getIterator();
}

// 具体集合类
class NameRepository implements Container {
    private String[] names = {"John", "Jane", "Joe"};

    public Iterator getIterator() {
        return new NameIterator();
    }

    private class NameIterator implements Iterator {
        int index;

        public boolean hasNext() {
            return index < names.length;
        }

        public Object next() {
            if (this.hasNext()) {
                return names[index++];
            }
            return null;
        }
    }
}

public class IteratorDemo {
    public static void main(String[] args) {
        NameRepository names = new NameRepository();
        Iterator iterator = names.getIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}
  • Iterator 接口定义了遍历方法,NameIterator 是具体的迭代器实现。

  • NameRepository 是集合类,提供了 getIterator() 方法来获取其内部元素的迭代器。

5. 中介者模式 (Mediator Pattern)

中介者模式定义了一个对象来封装一组对象之间的交互,使得这些对象不需要显式地彼此交互,而是通过中介者对象来协调。通过这种方式,可以减少对象之间的依赖关系。

实现方式

  • 定义一个中介者接口,所有的交互都通过它来进行。

  • 具体的中介者类实现该接口,并协调不同的组件对象。

Java实现

// 中介者接口
interface Mediator {
    void send(String message, Colleague colleague);
}
// 同事类接口
abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void receive(String message);
}

// 具体同事类
class ConcreteColleagueA extends Colleague {
    public ConcreteColleagueA(Mediator mediator) {
        super(mediator);
    }

    public void receive(String message) {
        System.out.println("Colleague A received: " + message);
    }

    public void send(String message) {
        mediator.send(message, this);
    }
}

class ConcreteColleagueB extends Colleague {
    public ConcreteColleagueB(Mediator mediator) {
        super(mediator);
    }

    public void receive(String message) {
        System.out.println("Colleague B received: " + message);
    }
// 具体中介者类
class ConcreteMediator implements Mediator {
    private ConcreteColleagueA colleagueA;
    private ConcreteColleagueB colleagueB;

    public void setColleagueA(ConcreteColleagueA colleagueA) {
        this.colleagueA = colleagueA;
    }

    public void setColleagueB(ConcreteColleagueB colleagueB) {
        this.colleagueB = colleagueB;
    }

    public void send(String message, Colleague colleague) {
        if (colleague == colleagueA) {
            colleagueB.receive(message);
        } else if (colleague == colleagueB) {
            colleagueA.receive(message);
        }
    }
}

public class MediatorDemo {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();

        ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);
        ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);

        mediator.setColleagueA(colleagueA);
        mediator.setColleagueB(colleagueB);

        colleagueA.send("Hello, B!");  // 输出: Colleague B received: Hello, B!
        colleagueB.send("Hello, A!");  // 输出: Colleague A received: Hello, A!
    }
}
  • Mediator 接口定义了协调不同同事之间的交互的方法。

  • ConcreteMediator 负责管理和协调 ConcreteColleagueAConcreteColleagueB 之间的通信。

  • ConcreteColleagueAConcreteColleagueB 通过中介者发送和接收消息,避免了它们之间的直接依赖。

6. 备忘录模式 (Memento Pattern)

备忘录模式用于保存和恢复对象的状态。它能够在不暴露对象实现的情况下,记录对象的状态,并在需要时恢复该状态。

实现方式

  • 定义一个备忘录类,负责存储对象的状态。

  • 定义一个发起人类,保存和恢复自身的状态。

  • 定义一个管理者类,负责备份和恢复发起人的状态。

Java实现

// 备忘录类
class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

// 发起人类
class Originator {
    private String state;

    public void setState(String state) {
        System.out.println("Setting state to: " + state);
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
        System.out.println("State after restoring: " + state);
    }
}

// 管理者类
class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}

public class MementoDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        originator.setState("State1");
        caretaker.add(originator.saveStateToMemento());

        originator.setState("State2");
        caretaker.add(originator.saveStateToMemento());

        originator.setState("State3");

        System.out.println("Current State: " + originator.getState());  // 输出: Current State: State3
        originator.getStateFromMemento(caretaker.get(0));
        System.out.println("First saved State: " + originator.getState());  // 输出: First saved State: State1
    }
}
  • Memento 类用于保存对象的状态。

  • Originator 类设置和获取对象的状态,并能够保存和恢复状态。

  • Caretaker 类负责管理多个备忘录,以便在需要时恢复状态。


7. 观察者模式 (Observer Pattern)

观察者模式定义了对象间一对多的依赖关系。多个观察者对象监听一个主题对象,当主题对象的状态发生变化时,它会通知所有的观察者对象。

实现方式

  • 定义一个主题接口,声明添加、删除和通知观察者的方法。

  • 观察者接口定义了响应更新的方法。

  • 主题类维护观察者的列表,并在状态变化时通知它们。

Java实现

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

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

// 具体观察者类
class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    public void update(String message) {
        System.out.println(name + " received message: " + message);
    }
}

// 具体主题类
class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String state;

    public void setState(String state) {
        this.state = state;
        notifyObservers();
    }

    public String getState() {
        return state;
    }

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
}

public class ObserverDemo {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();

        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");

        subject.addObserver(observer1);
        subject.addObserver(observer2);

        subject.setState("State 1");
        subject.setState("State 2");
    }
}
  • ConcreteSubject 类存储主题的状态并通知所有观察者。

  • ConcreteObserver 类根据主题状态的变化作出反应。


8. 状态模式 (State Pattern)

状态模式允许一个对象在其内部状态发生改变时改变其行为。对象在某个状态下的行为与在其他状态下的行为不同,状态模式允许对象的状态变化成为一种可管理的过程。

实现方式

  • 定义一个状态接口,声明不同状态下的行为。

  • 为每个具体状态创建一个类,并实现状态接口。

  • 上下文类持有当前状态,并根据状态变化执行不同的行为。

Java实现

// 状态接口
interface State {
    void handle();
}

// 具体状态类A
class ConcreteStateA implements State {
    public void handle() {
        System.out.println("Handling request in State A.");
    }
}

// 具体状态类B
class ConcreteStateB implements State {
    public void handle() {
        System.out.println("Handling request in State B.");
    }
}

// 上下文类
class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        state.handle();
    }
}

public class StateDemo {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());

        context.request();  // 输出: Handling request in State A.

        context.setState(new ConcreteStateB());
        context.request();  // 输出: Handling request in State B.
    }
}
  • Context 类持有当前的状态,并调用状态对象来处理请求。

  • ConcreteStateAConcreteStateB 定义了不同的状态行为。

9. 策略模式 (Strategy Pattern)

策略模式将一系列算法封装起来,使它们可以互相替换。策略模式让算法可以独立于使用它的客户端而变化。

实现方式

  • 定义一个策略接口,封装不同算法的执行方法。

  • 具体策略实现类定义不同的算法逻辑。

  • 上下文类持有策略接口的引用,通过设置不同策略来实现不同算法的切换。

Java实现

// 策略接口
interface Strategy {
    int execute(int a, int b);
}

// 具体策略类:加法
class AddStrategy implements Strategy {
    public int execute(int a, int b) {
        return a + b;
    }
}

// 具体策略类:减法
class SubtractStrategy implements Strategy {
    public int execute(int a, int b) {
        return a - b;
    }
}

// 具体策略类:乘法
class MultiplyStrategy implements Strategy {
    public int execute(int a, int b) {
        return a * b;
    }
}

// 上下文类
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }
}

public class StrategyDemo {
    public static void main(String[] args) {
        Context context = new Context(new AddStrategy());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context.setStrategy(new SubtractStrategy());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context.setStrategy(new MultiplyStrategy());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}
  • 不同的策略类实现了不同的算法操作。

  • 上下文类通过切换策略对象,实现算法运行方式的动态改变。


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

模板方法模式定义算法的骨架,并允许子类在不改变结构的情况下重定义其中的某些步骤。非常适合需要统一流程但部分步骤不同的场景。

实现方式

  • 抽象类定义算法骨架(模板方法)和部分抽象步骤。

  • 子类继承并实现具体步骤。

Java实现

// 抽象类:模板
abstract class Game {
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();

    // 模板方法
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }
}

// 具体子类
class Football extends Game {
    void initialize() {
        System.out.println("Football Game Initialized!");
    }
    void startPlay() {
        System.out.println("Football Game Started!");
    }
    void endPlay() {
        System.out.println("Football Game Finished!");
    }
}

public class TemplateDemo {
    public static void main(String[] args) {
        Game game = new Football();
        game.play();
    }
}
  • play() 是固定的流程框架,而具体步骤由子类决定。


11. 访问者模式 (Visitor Pattern)

访问者模式将数据结构与对结构的操作分离,使得在不改变类结构的情况下增加新的操作变得容易。

实现方式

  • 定义访问者接口,声明 visit 方法。

  • 对象结构类接受访问者对象,并调用访问者方法。

Java实现

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

// 访问者接口
interface Visitor {
    void visit(Book book);
    void visit(Computer computer);
}

// 具体元素
class Book implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class Computer implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体访问者
class DisplayVisitor implements Visitor {
    public void visit(Book book) {
        System.out.println("Displaying a Book");
    }
    public void visit(Computer computer) {
        System.out.println("Displaying a Computer");
    }
}

public class VisitorDemo {
    public static void main(String[] args) {
        Element[] elements = {new Book(), new Computer()};
        Visitor visitor = new DisplayVisitor();

        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}
  • 新增访问操作,只需要扩展访问者,而无需修改原来元素对象结构。


Comment