设计模式之行为型模式

发布时间:2024年01月16日

观察者模式(Observer Pattern)

  • 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
  • 观察者模式包含以下几个核心角色:
    1. 主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。
    2. 观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
    3. 具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。
    4. 具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。

观察者模式通过将主题和观察者解耦,实现了对象之间的松耦合。当主题的状态发生改变时,所有依赖于它的观察者都会收到通知并进行相应的更新。

以下是一个简单的观察者模式的 Java 示例代码:

import java.util.ArrayList;
import java.util.List;

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

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

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

    public int getState() {
        return state;
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

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

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

// 观察者接口
interface Observer {
    void update(int state);
}

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

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

    @Override
    public void update(int state) {
        System.out.println(name + " received update. New state: " + state);
    }
}

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

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

        subject.registerObserver(observer1);
        subject.registerObserver(observer2);

        subject.setState(10);

        subject.removeObserver(observer1);

        subject.setState(20);
    }
}

在上述示例中,观察者模式的核心是主题接口(Subject)和观察者接口(Observer),以及具体主题类(ConcreteSubject)和具体观察者类(ConcreteObserver)。具体主题类维护一个观察者列表,并在状态发生变化时通知所有观察者。具体观察者类实现了观察者接口,并在接收到更新通知时进行相应的操作。

在示例中,具体主题类是 ConcreteSubject,它维护了一个状态变量 state,并在状态发生变化时通过 notifyObservers() 方法通知所有观察者。具体观察者类是 ConcreteObserver,它实现了 update() 方法,在接收到更新通知时打印出新的状态。

在 main() 方法中,创建了一个具体主题对象和两个具体观察者对象,并通过 registerObserver() 方法将观察者注册到主题中。然后,通过 setState() 方法改变主题的状态,触发更新通知。最后,通过 removeObserver() 方法将一个观察者从主题中移除,并再次改变状态,触发更新通知。

策略模式(Strategy Pattern)

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。(在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。)

  • 策略模式包含以下几个核心角色:

    1. 环境(Context):维护一个对策略对象的引用,负责将客户端请求委派给具体的策略对象执行。环境类可以通过依赖注入、简单工厂等方式来获取具体策略对象。
    2. 抽象策略(Abstract Strategy):定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。
    3. 具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,包含了具体的算法实现。

策略模式通过将算法与使用算法的代码解耦,提供了一种动态选择不同算法的方法。客户端代码不需要知道具体的算法细节,而是通过调用环境类来使用所选择的策略。

以下是一个简单的策略模式的 Java 示例代码:

// 策略接口
interface Strategy {
    void execute();
}

// 具体策略类A
class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("Executing strategy A");
    }
}

// 具体策略类B
class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("Executing strategy B");
    }
}

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

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

    public void executeStrategy() {
        strategy.execute();
    }
}

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

        // 使用策略A
        Strategy strategyA = new ConcreteStrategyA();
        context.setStrategy(strategyA);
        context.executeStrategy();

        // 使用策略B
        Strategy strategyB = new ConcreteStrategyB();
        context.setStrategy(strategyB);
        context.executeStrategy();
    }
}

在上述示例中,策略模式的核心是策略接口(Strategy)和具体策略类(ConcreteStrategy),以及上下文类(Context)。策略接口定义了执行策略的方法,具体策略类实现了策略接口,并提供了不同的策略实现。上下文类包含一个策略对象,并在需要时调用策略对象的方法来执行具体的策略。

在示例中,策略接口是 Strategy,它定义了 execute() 方法。具体策略类 ConcreteStrategyA 和 ConcreteStrategyB 实现了 Strategy 接口,并分别提供了不同的策略实现。

上下文类是 Context,它包含一个策略对象,并提供了 setStrategy() 方法来设置具体的策略。executeStrategy() 方法用于执行当前设置的策略。

在 main() 方法中,创建了一个上下文对象和两个具体策略对象。通过 setStrategy() 方法将具体的策略设置到上下文中,然后调用 executeStrategy() 方法来执行当前设置的策略。

迭代器模式(Iterator Pattern)

意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
以下是一个简单的迭代器模式的 Java 示例代码:

import java.util.ArrayList;
import java.util.List;

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

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

// 具体迭代器类
class ConcreteIterator implements Iterator {
    private List<Object> items;
    private int position = 0;

    public ConcreteIterator(List<Object> items) {
        this.items = items;
    }

    @Override
    public boolean hasNext() {
        return position < items.size();
    }

    @Override
    public Object next() {
        if (hasNext()) {
            return items.get(position++);
        }
        return null;
    }
}

// 具体集合类
class ConcreteContainer implements Container {
    private List<Object> items = new ArrayList<>();

    public void addItem(Object item) {
        items.add(item);
    }

    @Override
    public Iterator getIterator() {
        return new ConcreteIterator(items);
    }
}

public class Main {
    public static void main(String[] args) {
        ConcreteContainer container = new ConcreteContainer();
        container.addItem("Item 1");
        container.addItem("Item 2");
        container.addItem("Item 3");

        Iterator iterator = container.getIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

在上述示例中,迭代器模式的核心是迭代器接口(Iterator)和集合接口(Container),以及具体迭代器类(ConcreteIterator)和具体集合类(ConcreteContainer)。迭代器接口定义了遍历集合元素的方法,集合接口定义了获取迭代器的方法。具体迭代器类实现了迭代器接口,具体集合类实现了集合接口。

在示例中,迭代器接口是 Iterator,它定义了 hasNext() 和 next() 方法。具体迭代器类 ConcreteIterator 实现了 Iterator 接口,并使用一个列表来存储元素,并追踪当前遍历的位置。

集合接口是 Container,它定义了获取迭代器的方法 getIterator()。具体集合类 ConcreteContainer 实现了 Container 接口,并使用一个列表来存储元素。它提供了 addItem() 方法用于向集合中添加元素,并通过 getIterator() 方法返回一个具体迭代器对象。

在 main() 方法中,创建了一个具体集合对象 ConcreteContainer,并使用 addItem() 方法向集合中添加元素。然后,通过 getIterator() 方法获取一个具体迭代器对象,并使用 while 循环遍历集合中的元素,并打印出来。

命令模式(Command Pattern)

  • 意图: 将请求封装成一个对象,使得可以用不同的请求对客户端进行参数化,同时支持请求的排队、记录日志、撤销等操作

  • 主要涉及到以下几个核心角色:

    1. 命令(Command):定义了执行操作的接口,通常包含一个 execute 方法,用于调用具体的操作。
    2. 具体命令(ConcreteCommand):实现了命令接口,负责执行具体的操作。它通常包含了对接收者的引用,通过调用接收者的方法来完成请求的处理。
    3. 接收者(Receiver):知道如何执行与请求相关的操作,实际执行命令的对象。
    4. 调用者/请求者(Invoker):发送命令的对象,它包含了一个命令对象并能触发命令的执行。调用者并不直接处理请求,而是通过将请求传递给命令对象来实现。
    5. 客户端(Client):创建具体命令对象并设置其接收者,将命令对象交给调用者执行
      以下是一个简单的命令模式的 Java 示例代码:
// 命令接口
interface Command {
    void execute();
}

// 具体命令类A
class ConcreteCommandA implements Command {
    private Receiver receiver;

    public ConcreteCommandA(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.actionA();
    }
}

// 具体命令类B
class ConcreteCommandB implements Command {
    private Receiver receiver;

    public ConcreteCommandB(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.actionB();
    }
}

// 接收者类
class Receiver {
    public void actionA() {
        System.out.println("Receiver executes action A");
    }

    public void actionB() {
        System.out.println("Receiver executes action B");
    }
}

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

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

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

public class Main {
    public static void main(String[] args) {
        Receiver receiver = new Receiver();

        Command commandA = new ConcreteCommandA(receiver);
        Command commandB = new ConcreteCommandB(receiver);

        Invoker invoker = new Invoker();

        // 执行命令A
        invoker.setCommand(commandA);
        invoker.executeCommand();

        // 执行命令B
        invoker.setCommand(commandB);
        invoker.executeCommand();
    }
}

在上述示例中,命令模式的核心是命令接口(Command)和具体命令类(ConcreteCommand),以及接收者类(Receiver)和调用者类(Invoker)。命令接口定义了执行命令的方法,具体命令类实现了命令接口,并提供了具体的命令实现。接收者类包含了实际执行命令的方法,调用者类持有一个命令对象,并在需要时调用命令对象的方法来执行相应的命令。

在示例中,命令接口是 Command,它定义了 execute() 方法。具体命令类 ConcreteCommandA 和 ConcreteCommandB 实现了 Command 接口,并分别提供了不同的命令实现,分别调用接收者的 actionA() 和 actionB() 方法。

接收者类是 Receiver,它包含了实际执行命令的方法 actionA() 和 actionB()。

调用者类是 Invoker,它持有一个命令对象,并提供了 setCommand() 方法来设置具体的命令。executeCommand() 方法用于执行当前设置的命令。

在 main() 方法中,创建了一个接收者对象 Receiver。然后,创建了具体命令对象 ConcreteCommandA 和 ConcreteCommandB,并将接收者对象传递给它们。接着,创建了调用者对象 Invoker,并通过 setCommand() 方法设置具体的命令。最后,调用 executeCommand() 方法来执行当前设置的命令。

状态模式(State Pattern)

  • 意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
    以下是一个简单的状态模式的 Java 示例代码:
// 状态接口
interface State {
    void handle();
}

// 具体状态类A
class ConcreteStateA implements State {
    @Override
    public void handle() {
        System.out.println("State A is handling");
    }
}

// 具体状态类B
class ConcreteStateB implements State {
    @Override
    public void handle() {
        System.out.println("State B is handling");
    }
}

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

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

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

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

        // 初始状态为A
        State stateA = new ConcreteStateA();
        context.setState(stateA);
        context.request();

        // 切换状态为B
        State stateB = new ConcreteStateB();
        context.setState(stateB);
        context.request();
    }
}

在上述示例中,状态模式的核心是状态接口(State)和具体状态类(ConcreteState),以及上下文类(Context)。状态接口定义了处理状态的方法,具体状态类实现了状态接口,并提供了不同的状态处理逻辑。上下文类包含一个状态对象,并在需要时调用状态对象的方法来处理当前状态。

在示例中,状态接口是 State,它定义了 handle() 方法。具体状态类 ConcreteStateA 和 ConcreteStateB 实现了 State 接口,并分别提供了不同的状态处理逻辑。

上下文类是 Context,它包含一个状态对象,并提供了 setState() 方法来设置具体的状态。request() 方法用于处理当前状态,实际上是调用当前状态对象的 handle() 方法。

在 main() 方法中,创建了一个上下文对象 Context。初始状态为 A,通过 setState() 方法将具体状态对象 ConcreteStateA 设置到上下文中,然后调用 request() 方法来处理当前状态。

接着,切换状态为 B,通过 setState() 方法将具体状态对象 ConcreteStateB 设置到上下文中,再次调用 request() 方法来处理当前状态。

责任链模式(Chain of Responsibility Pattern)

  • 意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
  • 主要涉及到以下几个核心角色:
    1. 抽象处理者(Handler): 定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者)。
    2. 具体处理者(ConcreteHandler): 实现了抽象处理者接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
    3. 客户端(Client): 创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。
      以下是一个简单的责任链模式的 Java 示例代码:
// 请求类
class Request {
    private String type;

    public Request(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

// 处理器接口
interface Handler {
    void setNextHandler(Handler handler);
    void handleRequest(Request request);
}

// 具体处理器类A
class ConcreteHandlerA implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler handler) {
        nextHandler = handler;
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getType().equals("TypeA")) {
            System.out.println("ConcreteHandlerA handles the request");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 具体处理器类B
class ConcreteHandlerB implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler handler) {
        nextHandler = handler;
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getType().equals("TypeB")) {
            System.out.println("ConcreteHandlerB handles the request");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 具体处理器类C
class ConcreteHandlerC implements Handler {
    private Handler nextHandler;

    @Override
    public void setNextHandler(Handler handler) {
        nextHandler = handler;
    }

    @Override
    public void handleRequest(Request request) {
        if (request.getType().equals("TypeC")) {
            System.out.println("ConcreteHandlerC handles the request");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 构建责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 创建请求
        Request request1 = new Request("TypeA");
        Request request2 = new Request("TypeB");
        Request request3 = new Request("TypeC");

        // 处理请求
        handlerA.handleRequest(request1);
        handlerA.handleRequest(request2);
        handlerA.handleRequest(request3);
    }
}

在上述示例中,责任链模式的核心是处理器接口(Handler)和具体处理器类(ConcreteHandler),以及请求类(Request)。处理器接口定义了设置下一个处理器和处理请求的方法,具体处理器类实现了处理器接口,并提供了不同的处理逻辑。请求类包含一个标识请求类型的属性。

在示例中,处理器接口是 Handler,它定义了 setNextHandler() 和 handleRequest() 方法。具体处理器类 ConcreteHandlerA、ConcreteHandlerB 和 ConcreteHandlerC 实现了 Handler 接口,并分别提供了不同的处理逻辑。

在具体处理器类的 handleRequest() 方法中,首先判断当前请求是否与处理器能够处理的类型匹配,如果匹配则处理请求,否则将请求传递给下一个处理器。如果没有下一个处理器,则请求无法被处理。

在 main() 方法中,创建了具体处理器对象 handlerA、handlerB 和 handlerC。然后,通过 setNextHandler() 方法构建了一个责任链,将 handlerB 设置为 handlerA 的下一个处理器,将 handlerC 设置为 handlerB 的下一个处理器。

接着,创建了三个请求对象 request1、request2 和 request3,分别设置了不同的类型。

最后,通过调用 handlerA 的 handleRequest() 方法来处理请求。根据请求类型,责任链会依次传递请求给各个处理器进行处理,直到找到能够处理该请求的处理器。

模板方法模式(Template Method Pattern)

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。子类可以不改变一个算法的结构也就是说可以重定义该算法的某些特定步骤。

以下是一个简单的模板方法模式的 Java 示例代码:

// 抽象模板类
abstract class AbstractClass {
    public void templateMethod() {
        commonOperation();
        specificOperation();
        abstractOperation();
        hook();
    }

    public void commonOperation() {
        System.out.println("This is a common operation");
    }

    public abstract void specificOperation();

    public abstract void abstractOperation();

    public void hook() {
        // 默认实现为空,子类可选择性地覆盖该方法
    }
}

// 具体模板类A
class ConcreteClassA extends AbstractClass {
    @Override
    public void specificOperation() {
        System.out.println("ConcreteClassA specific operation");
    }

    @Override
    public void abstractOperation() {
        System.out.println("ConcreteClassA abstract operation");
    }
}

// 具体模板类B
class ConcreteClassB extends AbstractClass {
    @Override
    public void specificOperation() {
        System.out.println("ConcreteClassB specific operation");
    }

    @Override
    public void abstractOperation() {
        System.out.println("ConcreteClassB abstract operation");
    }

    @Override
    public void hook() {
        System.out.println("ConcreteClassB hook operation");
    }
}

public class Main {
    public static void main(String[] args) {
        AbstractClass classA = new ConcreteClassA();
        AbstractClass classB = new ConcreteClassB();

        classA.templateMethod();
        System.out.println("--------------------");
        classB.templateMethod();
    }
}

在上述示例中,模板方法模式的核心是抽象模板类(AbstractClass)和具体模板类(ConcreteClass),以及模板方法(templateMethod)。抽象模板类定义了一个模板方法,该方法定义了一个算法的骨架,包含了一系列的步骤,其中一些步骤由子类实现。具体模板类继承抽象模板类,并实现了抽象方法和钩子方法。

在示例中,抽象模板类是 AbstractClass,它定义了 templateMethod() 方法作为模板方法。模板方法中依次调用了 commonOperation()、specificOperation()、abstractOperation() 和 hook() 方法。

具体模板类 ConcreteClassA 和 ConcreteClassB 继承了 AbstractClass,并分别实现了 specificOperation() 和 abstractOperation() 方法。

具体模板类可以选择性地覆盖 hook() 方法,该方法在模板方法中被调用,用于提供一个默认实现或留给子类自行决定是否覆盖。

在 main() 方法中,创建了具体模板类对象 classA 和 classB。然后,分别调用它们的 templateMethod() 方法来执行模板方法。

中介者模式(Mediator Pattern)

意图:用一个中介对象来封装一系列对象之间的交互,使得各个对象不需要显式地相互引用。
以下是一个简单的中介者模式的 Java 示例代码:

// 中介者接口
interface Mediator {
    void sendMessage(String message, Colleague colleague);
}

// 同事类接口
interface Colleague {
    void receiveMessage(String message);
    void sendMessage(String message);
}

// 具体中介者类
class ConcreteMediator implements Mediator {
    private Colleague colleagueA;
    private Colleague colleagueB;

    public void setColleagueA(Colleague colleague) {
        colleagueA = colleague;
    }

    public void setColleagueB(Colleague colleague) {
        colleagueB = colleague;
    }

    @Override
    public void sendMessage(String message, Colleague colleague) {
        if (colleague == colleagueA) {
            colleagueB.receiveMessage(message);
        } else if (colleague == colleagueB) {
            colleagueA.receiveMessage(message);
        }
    }
}

// 具体同事类A
class ConcreteColleagueA implements Colleague {
    private Mediator mediator;

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

    @Override
    public void receiveMessage(String message) {
        System.out.println("ConcreteColleagueA received message: " + message);
    }

    @Override
    public void sendMessage(String message) {
        mediator.sendMessage(message, this);
    }
}

// 具体同事类B
class ConcreteColleagueB implements Colleague {
    private Mediator mediator;

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

    @Override
    public void receiveMessage(String message) {
        System.out.println("ConcreteColleagueB received message: " + message);
    }

    @Override
    public void sendMessage(String message) {
        mediator.sendMessage(message, this);
    }
}

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

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

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

        colleagueA.sendMessage("Hello, colleagueB");
        colleagueB.sendMessage("Hi, colleagueA");
    }
}

在上述示例中,中介者模式的核心是中介者接口(Mediator)和同事类接口(Colleague),以及具体中介者类(ConcreteMediator)和具体同事类(ConcreteColleague)。中介者接口定义了发送消息的方法,同事类接口定义了接收消息和发送消息的方法。具体中介者类实现了中介者接口,并负责协调同事类之间的交互。具体同事类实现了同事类接口,并在需要时通过中介者发送和接收消息。

在示例中,中介者接口是 Mediator,它定义了 sendMessage() 方法。具体中介者类 ConcreteMediator 实现了 Mediator 接口,并实现了 sendMessage() 方法来协调同事类之间的消息传递。

同事类接口是 Colleague,它定义了 receiveMessage() 和 sendMessage() 方法。具体同事类 ConcreteColleagueA 和 ConcreteColleagueB 实现了 Colleague 接口,并分别实现了接收消息和发送消息的逻辑。

在 main() 方法中,创建了具体中介者对象 mediator,以及具体同事类对象 colleagueA 和 colleagueB。然后,通过 setColleagueA() 和 setColleagueB() 方法将同事类对象设置到中介者中。

最后,通过调用同事类的 sendMessage() 方法来发送消息。具体同事类会将消息传递给中介者,由中介者负责将消息发送给其他同事类。

访问者模式(Visitor Pattern)

意图:主要将数据结构与数据操作分离。在不改变被访问对象的前提下,定义作用于该对象的新操作。

以下是一个简单的访问者模式的 Java 示例代码:

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

// 具体访问者A
class ConcreteVisitorA implements Visitor {
    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("ConcreteVisitorA visits ConcreteElementA");
        element.operationA();
    }

    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("ConcreteVisitorA visits ConcreteElementB");
        element.operationB();
    }
}

// 具体访问者B
class ConcreteVisitorB implements Visitor {
    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("ConcreteVisitorB visits ConcreteElementA");
        element.operationA();
    }

   Override
    public void visit(ConcreteElementB element) {
        System.out.println("ConcreteVisitorB visits ConcreteElementB");
        element.operationB();
    }
}

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

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

    public void operationA() {
        System.out.println("ConcreteElementA operation");
    }
}

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

    public void operationB() {
        System.out.println("ConcreteElementB operation");
    }
}

// 对象结构
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void addElement(Element element) {
        elements.add(element);
    }

    public void removeElement(Element element) {
        elements.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.addElement(new ConcreteElementA());
        objectStructure.addElement(new ConcreteElementB());

        Visitor visitorA = new ConcreteVisitorA();
        Visitor visitorB = new ConcreteVisitorB();

        objectStructure.accept(visitorA);
        System.out.println("--------------------");
        objectStructure.accept(visitorB);
    }
}

在上述示例中,访问者模式的核心是访问者接口(Visitor)和元素接口(Element),以及具体访问者类(ConcreteVisitor)和具体元素类(ConcreteElement)。访问者接口定义了对每个元素进行操作的方法,元素接口定义了接受访问者的方法。具体访问者类实现了访问者接口,并对元素进行具体操作。具体元素类实现了元素接口,并将自身作为参数传递给访问者的具体方法。

在示例中,访问者接口是 Visitor,它定义了 visit() 方法。具体访问者类 ConcreteVisitorA 和 ConcreteVisitorB 实现了 Visitor 接口,并分别实现了 visit() 方法来对具体元素进行操作。

元素接口是 Element,它定义了 accept() 方法,该方法接收一个访问者作为参数。具体元素类 ConcreteElementA 和 ConcreteElementB 实现了 Element 接口,并分别实现了 accept() 方法,并将自身作为参数传递给访问者的具体方法。

对象结构类 ObjectStructure 包含了元素的集合,并提供了遍历元素的方法 accept()。

在 main() 方法中,创建了对象结构类 objectStructure,并添加了具体元素对象。然后,创建了具体访问者对象 visitorA 和 visitorB。

最后,通过调用对象结构类的 accept() 方法,将访问者对象传递给元素,实现对元素的操作。

解释器模式(Interpreter Pattern)

意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。(这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。)

以下是一个使用解释器模式的示例代码:

// 表达式接口
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);
    }
}

// 非终结符表达式类
class OrExpression implements Expression {
    private Expression expression1;
    private Expression expression2;

    public OrExpression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpret(String context) {
        return expression1.interpret(context) || expression2.interpret(context);
    }
}

// 非终结符表达式类
class AndExpression implements Expression {
    private Expression expression1;
    private Expression expression2;

    public AndExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpret(String context) {
        return expression1.interpret(context) && expression2.interpret(context);
    }
}

public class InterpreterPatternDemo {
    // 规则:John 和 Robert 是男性
    public static Expression getMaleExpression() {
        Expression john = new TerminalExpression("John");
        Expression robert = new TerminalExpression("Robert");
        return new OrExpression(john, robert);
    }

    // 规则:Julie 是已婚女性
    public static Expression getMarriedWomanExpression() {
        Expression julie = new TerminalExpression("Julie");
        Expression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);
    }

    public static void main(String[] args) {
        Expression isMale = getMaleExpression();
        Expression isMarriedWoman = getMarriedWomanExpression();

        System.out.println("John is male? " + isMale.interpret("John"));
        System.out.println("Julie is a married woman? " + isMarriedWoman.interpret("Married Julie"));
    }
}

在上述示例中,我们定义了一个表达式接口 Expression,其中包含一个 interpret() 方法用于解释表达式。

终结符表达式类 TerminalExpression 实现了 Expression 接口,它根据给定的数据来判断上下文中是否包含该数据。

非终结符表达式类 OrExpression 和 AndExpression 也实现了 Expression 接口,它们分别表示逻辑或和逻辑与的组合式表达式。

在 InterpreterPatternDemo 类中,我们定义了两个规则:getMaleExpression() 和 getMarriedWomanExpression()。这些规则使用了不同的表达式来创建组合式表达式。

在 main() 方法中,我们创建了具体的表达式对象 isMale 和 isMarriedWoman,并使用 interpret() 方法解释给定的上下文。最后,打印结果。

总结:行为型模式关注对象之间的通信和交互,旨在解决对象之间的责任分配和算法的封装。

文章来源:https://blog.csdn.net/qq_45450889/article/details/135592741
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。