Skip to content

行为型

责任链模式(Chain of Responsibility)

避免请求发送者与接收者之间的耦合关系,让多个对象都有机会处理这个请求。符合单一职责原则最少知识原则优点:

  • 该模式降低了请求发送者和接收者的耦合度。
  • 可以根据需要增加新的请求处理类,满足开闭原则。
  • 当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。
  • 一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
  • 每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

缺点:

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
  • Java代码演示
java
public abstract class Handler {
    protected final static int NUM_ONE = 1;
    protected final static int NUM_THREE = 3;
    protected final static int NUM_SEVEN = 7;

    private int numStart;

    private int numEnd;

    private Handler nextHandler;

    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    protected abstract void handleLeave(LeaveRequest leaveRequest);

    public void submit(LeaveRequest leaveRequest) {
        this.handleLeave(leaveRequest);
        if (this.nextHandler != null && leaveRequest.getNum() > this.numEnd) {
            this.nextHandler.submit(leaveRequest);
        }else {
            System.out.println("流程结束!");
        }
    }
}
java
public class GeneralManger extends Handler{
    public GeneralManger() {
        super(Handler.NUM_THREE,Handler.NUM_SEVEN);
    }

    @Override
    protected void handleLeave(LeaveRequest leaveRequest) {
        System.out.println(leaveRequest.getName() + "请假" + leaveRequest.getNum() + "天" + leaveRequest.getContent());
        System.out.println("总经理审批: 同意");
    }
}
public class GroupLeader extends Handler {
    public GroupLeader() {
        super(0, Handler.NUM_ONE);
    }

    @Override
    protected void handleLeave(LeaveRequest leaveRequest) {
        System.out.println(leaveRequest.getName() + "请假" + leaveRequest.getNum() + "天" + leaveRequest.getContent());
        System.out.println("小组长审批: 同意");
    }
}
public class Manager extends Handler {
    public Manager() {
        super(Handler.NUM_ONE, Handler.NUM_THREE);
    }

    @Override
    protected void handleLeave(LeaveRequest leaveRequest) {
        System.out.println(leaveRequest.getName() + "请假" + leaveRequest.getNum() + "天" + leaveRequest.getContent());
        System.out.println("部门经理审批: 同意");
    }
}
java
public class LeaveRequest {
    private String name;

    private int num;

    private String content;

    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }
}
java
public class Client {
    public static void main(String[] args) {
        LeaveRequest leaveRequest = new LeaveRequest("小明", 4, "身体不适");

        GroupLeader groupLeader = new GroupLeader();
        Manager manager = new Manager();
        GeneralManger generalManger = new GeneralManger();

        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManger);

        groupLeader.submit(leaveRequest);
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <string>
#include <memory>

// 请假请求
class LeaveRequest {
private:
    std::string name;
    int num;
    std::string content;

public:
    LeaveRequest(const std::string& name, int num, const std::string& content)
        : name(name), num(num), content(content) {}

    std::string getName() const {
        return name;
    }

    int getNum() const {
        return num;
    }

    std::string getContent() const {
        return content;
    }
};

// 抽象处理者
class Handler {
protected:
    static const int NUM_ONE = 1;
    static const int NUM_THREE = 3;
    static const int NUM_SEVEN = 7;

    int numStart;
    int numEnd;
    std::shared_ptr<Handler> nextHandler; // 使用 shared_ptr

public:
    Handler(int numStart, int numEnd) : numStart(numStart), numEnd(numEnd) {}
    virtual ~Handler() = default; // 虚析构函数

    void setNextHandler(std::shared_ptr<Handler> nextHandler) {
        this->nextHandler = nextHandler;
    }

    virtual void handleLeave(LeaveRequest leaveRequest) = 0; // 纯虚函数

    void submit(LeaveRequest leaveRequest) {
        handleLeave(leaveRequest);
        if (nextHandler && leaveRequest.getNum() > numEnd) {
            nextHandler->submit(leaveRequest);
        } else {
            std::cout << "流程结束!" << std::endl;
        }
    }
};

// 小组长
class GroupLeader : public Handler {
public:
    GroupLeader() : Handler(0, Handler::NUM_ONE) {}

protected:
    void handleLeave(LeaveRequest leaveRequest) override {
        std::cout << leaveRequest.getName() << "请假" << leaveRequest.getNum() << "天"
                  << leaveRequest.getContent() << std::endl;
        std::cout << "小组长审批: 同意" << std::endl;
    }
};

// 部门经理
class Manager : public Handler {
public:
    Manager() : Handler(Handler::NUM_ONE, Handler::NUM_THREE) {}

protected:
    void handleLeave(LeaveRequest leaveRequest) override {
        std::cout << leaveRequest.getName() << "请假" << leaveRequest.getNum() << "天"
                  << leaveRequest.getContent() << std::endl;
        std::cout << "部门经理审批: 同意" << std::endl;
    }
};

// 总经理
class GeneralManger : public Handler {
public:
    GeneralManger() : Handler(Handler::NUM_THREE, Handler::NUM_SEVEN) {}

protected:
    void handleLeave(LeaveRequest leaveRequest) override {
        std::cout << leaveRequest.getName() << "请假" << leaveRequest.getNum() << "天"
                  << leaveRequest.getContent() << std::endl;
        std::cout << "总经理审批: 同意" << std::endl;
    }
};

int main() {
    LeaveRequest leaveRequest("小明", 4, "身体不适");

    auto groupLeader = std::make_shared<GroupLeader>();
    auto manager = std::make_shared<Manager>();
    auto generalManger = std::make_shared<GeneralManger>();

    groupLeader->setNextHandler(manager);
    manager->setNextHandler(generalManger);

    groupLeader->submit(leaveRequest);

    return 0;
}

命令模式(Command)

将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化。符合单一职责原则

优点:

  • 命令模式能将调用操作的对象与实现该操作的对象解耦。 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足开闭原则,对扩展比较灵活。
  • 命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  • 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。
  • 系统结构更加复杂。

使用场景

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。

  • 系统需要在不同的时间指定请求、将请求排队和执行请求。

  • 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

  • Java代码演示

java
public interface Command {
    void execute();
}
public class OrderCommand implements Command{
    private SeniorChef receiver;
    private Order order;

    public OrderCommand(SeniorChef receiver, Order order) {
        this.receiver = receiver;
        this.order = order;
    }

    @Override
    public void execute() {
        System.out.println(order.getDiningTable() + "卓的订单: ");
        order.getFoodDir().forEach((name,num)-> receiver.makeFood(name,num));

        System.out.println(order.getDiningTable() + "卓的订单准备完毕!!");
    }
}
java
public class Order {
    private int diningTable;

    private Map<String,Integer> foodDir = new HashMap<>();

    public Map<String, Integer> getFoodDir() {
        return foodDir;
    }

    public void setFood(String name,int num) {
        foodDir.put(name,num);
    }

    public int getDiningTable() {
        return diningTable;
    }

    public void setDiningTable(int diningTable) {
        this.diningTable = diningTable;
    }
}
java
//请求者(调用者角色)
//持有多个命令对象
public class Waitor {
    private List<Command> commands = new ArrayList<>();

    public void addCommand(Command command) {
        commands.add(command);
    }

    public void orderUp() {
        System.out.println("Order up");
        commands.forEach(command -> {
            if (command != null) command.execute();
        });
    }
}
java
public class SeniorChef {
    public void makeFood(String name,int num) {
        System.out.println(num + "份" + name);
    }
}
java
public class Client {
    public static void main(String[] args) {
        Order order1 = new Order();
        order1.setDiningTable(1);
        order1.setFood("西红柿鸡蛋面",1);
        order1.setFood("可乐",2);

        Order order2 = new Order();
        order2.setDiningTable(1);
        order2.setFood("西红柿牛肉面",1);
        order2.setFood("橙汁",1);

        SeniorChef receiver = new SeniorChef();
        OrderCommand orderCommand1 = new OrderCommand(receiver, order1);
        OrderCommand orderCommand2 = new OrderCommand(receiver, order2);

        Waitor invoke = new Waitor();
        invoke.addCommand(orderCommand1);
        invoke.addCommand(orderCommand2);

        invoke.orderUp();
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <functional> // for std::function
#include <memory>

// 命令接口
class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() = default; // 虚析构函数
};

// 订单命令
class OrderCommand : public Command {
private:
    std::shared_ptr<SeniorChef> receiver;
    std::shared_ptr<Order> order;

public:
    OrderCommand(std::shared_ptr<SeniorChef> receiver, std::shared_ptr<Order> order)
        : receiver(receiver), order(order) {}

    void execute() override {
        std::cout << order->getDiningTable() << "卓的订单: " << std::endl;
        for (const auto& [name, num] : order->getFoodDir()) {
            receiver->makeFood(name, num);
        }
        std::cout << order->getDiningTable() << "卓的订单准备完毕!!" << std::endl;
    }
};

// 订单
class Order {
private:
    int diningTable;
    std::map<std::string, int> foodDir;

public:
    std::map<std::string, int> getFoodDir() const {
        return foodDir;
    }

    void setFood(const std::string& name, int num) {
        foodDir[name] = num;
    }

    int getDiningTable() const {
        return diningTable;
    }

    void setDiningTable(int diningTable) {
        this->diningTable = diningTable;
    }
};

// 服务员(调用者)
class Waitor {
private:
    std::vector<std::shared_ptr<Command>> commands;

public:
    void addCommand(std::shared_ptr<Command> command) {
        commands.push_back(command);
    }

    void orderUp() {
        std::cout << "Order up" << std::endl;
        for (const auto& command : commands) {
            if (command) {
                command->execute();
            }
        }
    }
};

// 高级厨师(接收者)
class SeniorChef {
public:
    void makeFood(const std::string& name, int num) {
        std::cout << num << "份" << name << std::endl;
    }
};

int main() {
    auto order1 = std::make_shared<Order>();
    order1->setDiningTable(1);
    order1->setFood("西红柿鸡蛋面", 1);
    order1->setFood("可乐", 2);

    auto order2 = std::make_shared<Order>();
    order2->setDiningTable(1);
    order2->setFood("西红柿牛肉面", 1);
    order2->setFood("橙汁", 1);

    auto receiver = std::make_shared<SeniorChef>();
    auto orderCommand1 = std::make_shared<OrderCommand>(receiver, order1);
    auto orderCommand2 = std::make_shared<OrderCommand>(receiver, order2);

    Waitor invoke;
    invoke.addCommand(orderCommand1);
    invoke.addCommand(orderCommand2);

    invoke.orderUp();

    return 0;
}

解释器模式(Interpreter)

给定一个语言,定义它的文法,并且提供一个解释器来解释句子。符合单一职责原则

优点:

  • 由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  • 在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂。
  • 如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合 "开闭原则"。

缺点:

  • 在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护。
  • 由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

使用场景

  • 当语言的文法较为简单,且执行效率不是关键问题时。

  • 当问题重复出现,且可以用一种简单的语言来进行表达时。

  • 当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候。

  • Java代码演示

java
public abstract class AbstractExpression {
    public abstract int interpret(Context context);
}
///非终结符表达式角色
public class Minus extends AbstractExpression{
    private AbstractExpression left;
    private AbstractExpression right;

    public Minus(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) - right.interpret(context);
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " - " + right.toString() + ")";
    }
}
///非终结符表达式角色
public class Plus extends AbstractExpression{
    private AbstractExpression left;
    private AbstractExpression right;

    public Plus(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) + right.interpret(context);
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " + " + right.toString() + ")";
    }
}
//终结符表达式角色
public class Variable extends AbstractExpression{
    private String name;

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

    @Override
    public int interpret(Context context) {
        return context.getValue(this);
    }

    @Override
    public String toString() {
        return name;
    }
}
java
//通常包含各个解释器需要的数据或是公共的功能,
//一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值
import java.util.HashMap;
import java.util.Map;

public class Context {
    private Map<Variable, Integer> map = new HashMap<>();

    public void assign(Variable variable, int value) {
        map.put(variable, value);
    }

    public int getValue(Variable variable) {
        return map.get(variable);
    }
}
java
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        Variable a = new Variable("a");
        Variable b = new Variable("b");
        Variable c = new Variable("c");
        Variable d = new Variable("d");

        context.assign(a, 1);
        context.assign(b, 2);
        context.assign(c, 3);
        context.assign(d, 4);
        //
        AbstractExpression expression = new Minus(a, new Plus(new Minus(b, c), d));
        int result = expression.interpret(context);
        System.out.println(expression + " = "+result);
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <string>
#include <memory>
#include <map>

// 抽象表达式
class AbstractExpression {
public:
    virtual int interpret(const std::map<std::string, int>& context) const = 0;
    virtual std::string toString() const = 0;
    virtual ~AbstractExpression() = default; // 虚析构函数
};

// 减法表达式
class Minus : public AbstractExpression {
private:
    std::shared_ptr<AbstractExpression> left;
    std::shared_ptr<AbstractExpression> right;

public:
    Minus(std::shared_ptr<AbstractExpression> left, std::shared_ptr<AbstractExpression> right)
        : left(left), right(right) {}

    int interpret(const std::map<std::string, int>& context) const override {
        return left->interpret(context) - right->interpret(context);
    }

    std::string toString() const override {
        return "(" + left->toString() + " - " + right->toString() + ")";
    }
};

// 加法表达式
class Plus : public AbstractExpression {
private:
    std::shared_ptr<AbstractExpression> left;
    std::shared_ptr<AbstractExpression> right;

public:
    Plus(std::shared_ptr<AbstractExpression> left, std::shared_ptr<AbstractExpression> right)
        : left(left), right(right) {}

    int interpret(const std::map<std::string, int>& context) const override {
        return left->interpret(context) + right->interpret(context);
    }

    std::string toString() const override {
        return "(" + left->toString() + " + " + right->toString() + ")";
    }
};

// 变量表达式
class Variable : public AbstractExpression {
private:
    std::string name;

public:
    Variable(const std::string& name) : name(name) {}

    int interpret(const std::map<std::string, int>& context) const override {
        auto it = context.find(name);
        if (it != context.end()) {
            return it->second;
        } else {
            throw std::runtime_error("Variable not found in context: " + name); // 处理找不到变量的情况
        }
    }

    std::string toString() const override {
        return name;
    }
};


int main() {
    std::map<std::string, int> context;
    auto a = std::make_shared<Variable>("a");
    auto b = std::make_shared<Variable>("b");
    auto c = std::make_shared<Variable>("c");
    auto d = std::make_shared<Variable>("d");

    context["a"] = 1;
    context["b"] = 2;
    context["c"] = 3;
    context["d"] = 4;

    auto expression = std::make_shared<Minus>(a, std::make_shared<Plus>(std::make_shared<Minus>(b, c), d));
    int result = expression->interpret(context);
    std::cout << expression->toString() << " = " << result << std::endl;

    return 0;
}

迭代器模式(Iterator)

提供一种方法顺序访问一个集合对象中的元素,而不暴露该对象的内部表示。符合最少知识原则优点:

  • 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
  • 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。

缺点:

  • 增加了类的个数,这在一定程度上增加了系统的复杂性。

使用场景

  • 当需要为聚合对象提供多种遍历方式时。

  • 当需要为遍历不同的聚合结构提供一个统一的接口时。

  • 当访问一个聚合对象的内容而无须暴露其内部细节的表示时。

  • Java代码演示

java
public interface StudentIterator {
    boolean hasNext();
    Student next();
}
public class StudentIteratorImpl implements StudentIterator{
    private List<Student> students;
    private int position = 0;

    public StudentIteratorImpl(List<Student> students) {
        this.students = students;
    }

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

    @Override
    public Student next() {
        Student student = students.get(position);
        position++;
        return student;
    }
}
java
public interface StudentAggregate {
    void addStudent(Student student);

    void removeStudent(Student student);

    StudentIterator getStudentIterator();
}
public class StudentAggregateImpl implements StudentAggregate{
    private List<Student> students = new ArrayList<>();

    @Override
    public void addStudent(Student student) {
        students.add(student);
    }

    @Override
    public void removeStudent(Student student) {
        students.remove(student);
    }

    @Override
    public StudentIterator getStudentIterator() {
        return new StudentIteratorImpl(students);
    }
}
java
public class Student {
    private String name;
    private String number;

    public Student(String name, String number) {
        this.name = name;
        this.number = number;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", number='" + number + '\'' +
                '}';
    }
}
java
public class Client {
    public static void main(String[] args) {
        StudentAggregateImpl aggregate = new StudentAggregateImpl();
        aggregate.addStudent(new Student("张三","001"));
        aggregate.addStudent(new Student("李四","002"));
        aggregate.addStudent(new Student("王五","003"));
        aggregate.addStudent(new Student("赵六","004"));

        StudentIterator iterator = aggregate.getStudentIterator();
        while (iterator.hasNext()) {
            Student student = iterator.next();
            System.out.println(student.toString());
        }
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>

// 学生类
class Student {
private:
    std::string name;
    std::string number;

public:
    Student(const std::string& name, const std::string& number) : name(name), number(number) {}

    std::string getName() const { return name; }
    std::string getNumber() const { return number; }

    std::string toString() const {
        return "Student{name='" + name + "', number='" + number + "'}";
    }
};

// 学生迭代器接口
class StudentIterator {
public:
    virtual bool hasNext() = 0;
    virtual std::shared_ptr<Student> next() = 0; // 返回 shared_ptr
    virtual ~StudentIterator() = default; // 虚析构函数
};

// 学生迭代器实现
class StudentIteratorImpl : public StudentIterator {
private:
    std::vector<std::shared_ptr<Student>> students; // 存储 shared_ptr
    int position = 0;

public:
    StudentIteratorImpl(const std::vector<std::shared_ptr<Student>>& students) : students(students) {}

    bool hasNext() override {
        return position < students.size();
    }

    std::shared_ptr<Student> next() override { // 返回 shared_ptr
        if (!hasNext()) {
          return nullptr; // 或者抛出异常,取决于你的设计
        }
        std::shared_ptr<Student> student = students[position];
        position++;
        return student;
    }
};

// 学生聚合接口
class StudentAggregate {
public:
    virtual void addStudent(std::shared_ptr<Student> student) = 0;
    virtual void removeStudent(std::shared_ptr<Student> student) = 0;
    virtual std::shared_ptr<StudentIterator> getStudentIterator() = 0; // 返回 shared_ptr
    virtual ~StudentAggregate() = default; // 虚析构函数
};

// 学生聚合实现
class StudentAggregateImpl : public StudentAggregate {
private:
    std::vector<std::shared_ptr<Student>> students; // 存储 shared_ptr

public:
    void addStudent(std::shared_ptr<Student> student) override {
        students.push_back(student);
    }

    void removeStudent(std::shared_ptr<Student> student) override {
        // 使用迭代器删除元素,更安全
        for (auto it = students.begin(); it != students.end(); ++it) {
            if (*it == student) {
                students.erase(it);
                return; // 找到并删除后退出
            }
        }
    }

    std::shared_ptr<StudentIterator> getStudentIterator() override { // 返回 shared_ptr
        return std::make_shared<StudentIteratorImpl>(students);
    }
};

int main() {
    auto aggregate = std::make_shared<StudentAggregateImpl>();

    aggregate->addStudent(std::make_shared<Student>("张三", "001"));
    aggregate->addStudent(std::make_shared<Student>("李四", "002"));
    aggregate->addStudent(std::make_shared<Student>("王五", "003"));
    aggregate->addStudent(std::make_shared<Student>("赵六", "004"));

    auto iterator = aggregate->getStudentIterator();
    while (iterator->hasNext()) {
        auto student = iterator->next();
        if (student) { // 检查是否为空,避免空指针解引用
            std::cout << student->toString() << std::endl;
        }
    }

    return 0;
}

中介者模式(Mediator)

用一个中介对象来封装一系列对象的交互。符合最少知识原则单一职责原则优点:

  • 中介者模式通过把多个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互补依赖。这样一来,同事对象就可以独立地变化和复用,而不再像以前那样牵一处而动全身了。
  • 多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改中介者对象就可以了,当然如果是已经做好的系统,那么就扩展中介者对象,而各个同事类不需要做修改。
  • 没有使用中介者模式的时候,同事对象之间的关系通常是一对多的,引入中介者对象以后,中介者对象和同事对象的关系通常变成双向的一对一,这会让对象的关系更容易理解和实现。

缺点:

  • 当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。

使用场景

  • 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。

  • 当想创建一个运行于多个类之间的对象,又不想生成新的子类时。

  • Java代码演示

java
public abstract class Person {
    protected String name;
    protected Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
}
public class Tenant extends Person {
    public Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }

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

    public void getMessage(String message) {
        System.out.println("租房者: " + name + "获取到的信息是: " + message);
    }
}
public class HouseOwner extends Person{
    public HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }

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

    public void getMessage(String message) {
        System.out.println("房主: " + name + "获取到的信息是: " + message);
    }
}
java
public abstract class Mediator {
    public abstract void constact(String message,Person person);
}
public class MediatorStructure extends Mediator{
    private HouseOwner houseOwner;
    private Tenant tenant;

    public HouseOwner getHouseOwner() {
        return houseOwner;
    }

    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }

    public Tenant getTenant() {
        return tenant;
    }

    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }

    @Override
    public void constact(String message, Person person) {
        if(person == houseOwner) tenant.getMessage(message);
        else houseOwner.getMessage(message);
    }
}
java
public class Client {
    public static void main(String[] args) {
        MediatorStructure mediator = new MediatorStructure();

        Tenant tenant = new Tenant("李四", mediator);
        HouseOwner houseOwner = new HouseOwner("张三", mediator);

        mediator.setTenant(tenant);
        mediator.setHouseOwner(houseOwner);

        tenant.constact("我要租三室一厅的房子");
        houseOwner.constact("我有四室一厅的房子");
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <string>
#include <memory>

// 前置声明,解决循环依赖问题
class HouseOwner;
class Tenant;

// 调解器抽象类
class Mediator {
public:
    virtual void contact(const std::string& message, Person* person) = 0;
    virtual ~Mediator() = default; // 虚析构函数
};

// 人抽象类
class Person {
protected:
    std::string name;
    Mediator* mediator; // 使用指针

public:
    Person(const std::string& name, Mediator* mediator) : name(name), mediator(mediator) {}
    virtual ~Person() = default; // 虚析构函数

    virtual void contact(const std::string& message) = 0;
    virtual void getMessage(const std::string& message) = 0;
};

// 租户
class Tenant : public Person {
public:
    Tenant(const std::string& name, Mediator* mediator) : Person(name, mediator) {}

    void contact(const std::string& message) override {
        mediator->contact(message, this);
    }

    void getMessage(const std::string& message) override {
        std::cout << "租房者: " << name << "获取到的信息是: " << message << std::endl;
    }
};

// 房主
class HouseOwner : public Person {
public:
    HouseOwner(const std::string& name, Mediator* mediator) : Person(name, mediator) {}

    void contact(const std::string& message) override {
        mediator->contact(message, this);
    }

    void getMessage(const std::string& message) override {
        std::cout << "房主: " << name << "获取到的信息是: " << message << std::endl;
    }
};

// 调解器结构
class MediatorStructure : public Mediator {
private:
    HouseOwner* houseOwner; // 使用指针
    Tenant* tenant;         // 使用指针

public:
    HouseOwner* getHouseOwner() const {
        return houseOwner;
    }

    void setHouseOwner(HouseOwner* houseOwner) {
        this->houseOwner = houseOwner;
    }

    Tenant* getTenant() const {
        return tenant;
    }

    void setTenant(Tenant* tenant) {
        this->tenant = tenant;
    }

    void contact(const std::string& message, Person* person) override {
        if (person == houseOwner) {
            if (tenant) tenant->getMessage(message); // 检查指针是否为空
        } else {
           if (houseOwner) houseOwner->getMessage(message); // 检查指针是否为空
        }
    }
};

int main() {
    MediatorStructure mediator;

    Tenant tenant("李四", &mediator);  // 注意这里是 &mediator
    HouseOwner houseOwner("张三", &mediator); // 注意这里是 &mediator

    mediator.setTenant(&tenant);      // 注意这里是 &tenant
    mediator.setHouseOwner(&houseOwner); // 注意这里是 &houseOwner

    tenant.contact("我要租三室一厅的房子");
    houseOwner.contact("我有四室一厅的房子");

    return 0;
}

备忘录模式(Memento)

在不破坏封装性的前提下,捕获一个对象的内部状态,并在以后恢复它。符合单一职责原则

  • Java代码演示
java
// Memento 类,保存 Originator 的状态
class Memento {
    private String state;

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

    public String getState() {
        return state;
    }
}

// Originator 类,拥有要保存的状态
class Originator {
    private String state;

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

    public String getState() {
        return state;
    }

    // 创建一个备忘录
    public Memento saveStateToMemento() {
        System.out.println("Originator: Saving state to Memento");
        return new Memento(state);
    }

    // 从备忘录恢复状态
    public void restoreStateFromMemento(Memento memento) {
        state = memento.getState();
        System.out.println("Originator: State after restoring from Memento: " + state);
    }
}

// Caretaker 类,负责保存和恢复备忘录
class Caretaker {
    private Memento memento;

    public void saveMemento(Memento memento) {
        this.memento = memento;
    }

    public Memento getMemento() {
        return memento;
    }
}

// 客户端代码
public class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        // 设置状态并保存备忘录
        originator.setState("State1");
        caretaker.saveMemento(originator.saveStateToMemento());

        // 改变状态
        originator.setState("State2");

        // 恢复状态
        originator.restoreStateFromMemento(caretaker.getMemento());
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <memory>
#include <string>

// Memento 类,保存 Originator 的状态
class Memento {
private:
    std::string state;

public:
    Memento(const std::string& state) : state(state) {}

    std::string getState() const {
        return state;
    }
};

// Originator 类,拥有要保存的状态
class Originator {
private:
    std::string state;

public:
    void setState(const std::string& state) {
        this->state = state;
        std::cout << "Originator: Setting state to " << state << std::endl;
    }

    std::string getState() const {
        return state;
    }

    // 创建一个备忘录
    std::shared_ptr<Memento> saveStateToMemento() {
        std::cout << "Originator: Saving state to Memento" << std::endl;
        return std::make_shared<Memento>(state);
    }

    // 从备忘录恢复状态
    void restoreStateFromMemento(const std::shared_ptr<Memento>& memento) {
        state = memento->getState();
        std::cout << "Originator: State after restoring from Memento: " << state << std::endl;
    }
};

// Caretaker 类,负责保存和恢复备忘录
class Caretaker {
private:
    std::shared_ptr<Memento> memento;

public:
    void saveMemento(const std::shared_ptr<Memento>& memento) {
        this->memento = memento;
    }

    std::shared_ptr<Memento> getMemento() const {
        return memento;
    }
};

// 客户端代码
int main() {
    Originator originator;
    Caretaker caretaker;

    // 设置状态并保存备忘录
    originator.setState("State1");
    caretaker.saveMemento(originator.saveStateToMemento());

    // 改变状态
    originator.setState("State2");

    // 恢复状态
    originator.restoreStateFromMemento(caretaker.getMemento());

    return 0;
}

观察者模式(Observer)

定义对象间的一种一对多的依赖关系,使得当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。符合依赖倒置原则

优点:

  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  • 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】

缺点:

  • 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
  • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃

使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。

  • Java代码演示

java
public interface Observer {
    void update(String message);
}
public class WechatUser implements Observer{
    private String name;
    @Override
    public void update(String message) {
        System.out.println(name + ": " + message);
    }

    public WechatUser(String name) {
        this.name = name;
    }
}
java
public interface Subject {
    void attach(Observer observer);

    void detach(Observer observer);

    void notify(String message);
}
public class SubscriptionSubject implements Subject{
    List<Observer> weChatUserList = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        weChatUserList.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        weChatUserList.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (Observer observer : weChatUserList) {
            observer.update(message);
        }
    }
}
java
public class Client {
    public static void main(String[] args) {
        SubscriptionSubject subject = new SubscriptionSubject();

        subject.attach(new WechatUser("Tom"));
        subject.attach(new WechatUser("Jack"));
        subject.attach(new WechatUser("Jerry"));

        subject.notify("云间幽谷更新了");


    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm> // for std::remove

// 观察者接口
class Observer {
public:
    virtual void update(const std::string& message) = 0;
    virtual ~Observer() = default; // 虚析构函数
};

// 微信用户
class WechatUser : public Observer {
private:
    std::string name;

public:
    WechatUser(const std::string& name) : name(name) {}

    void update(const std::string& message) override {
        std::cout << name << ": " << message << std::endl;
    }
};

// 主题接口
class Subject {
public:
    virtual void attach(std::shared_ptr<Observer> observer) = 0;
    virtual void detach(std::shared_ptr<Observer> observer) = 0;
    virtual void notify(const std::string& message) = 0;
    virtual ~Subject() = default; // 虚析构函数
};

// 订阅主题
class SubscriptionSubject : public Subject {
private:
    std::vector<std::shared_ptr<Observer>> weChatUserList;

public:
    void attach(std::shared_ptr<Observer> observer) override {
        weChatUserList.push_back(observer);
    }

    void detach(std::shared_ptr<Observer> observer) override {
        // 使用 erase-remove idiom 安全地删除元素
        weChatUserList.erase(std::remove(weChatUserList.begin(), weChatUserList.end(), observer), weChatUserList.end());
    }

    void notify(const std::string& message) override {
        for (const auto& observer : weChatUserList) {
            observer->update(message);
        }
    }
};

int main() {
    auto subject = std::make_shared<SubscriptionSubject>();

    subject->attach(std::make_shared<WechatUser>("Tom"));
    subject->attach(std::make_shared<WechatUser>("Jack"));
    subject->attach(std::make_shared<WechatUser>("Jerry"));

    subject->notify("云间幽谷更新了");

    return 0;
}

状态模式(State)

允许一个对象在其内部状态改变时改变它的行为。符合开放封闭原则

优点:

  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

缺点:

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对"开闭原则"的支持并不太好。

使用场景

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。

  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。

  • Java代码演示

java
public abstract class LiftState {
    protected Context context;

    public void setContext(Context context) {
        this.context = context;
    }

    public abstract void open();
    public abstract void close();
    public abstract void run();
    public abstract void stop();
}
//关闭状态
public class ClosingState extends LiftState {

    @Override
    //电梯门关闭,这是关闭状态要实现的动作
    public void close() {
        System.out.println("电梯门关闭...");
    }

    //电梯门关了再打开,逗你玩呢,那这个允许呀
    @Override
    public void open() {
        super.context.setLiftState(Context.OPENING_STATE);
        super.context.open();
    }

    //电梯门关了就跑,这是再正常不过了
    @Override
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE);
        super.context.run();
    }

    //电梯门关着,我就不按楼层
    @Override
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.stop();
    }
}

public class OpeningState extends LiftState{
    @Override
    public void open() {
        System.out.println("Opening....");
    }

    @Override
    public void close() {
        super.context.setLiftState(Context.CLOSING_STATE);
        super.context.close();
    }

    @Override
    public void run() {

    }

    @Override
    public void stop() {

    }
}

public class RunningState extends LiftState {
    //运行的时候开电梯门?你疯了!电梯不会给你开的
    @Override
    public void open() {
        //do nothing
    }

    //电梯门关闭?这是肯定了
    @Override
    public void close() {//虽然可以关门,但这个动作不归我执行
        //do nothing
    }

    //这是在运行状态下要实现的方法
    @Override
    public void run() {
        System.out.println("电梯正在运行...");
    }

    //这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了
    @Override
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.stop();
    }
}

public class StoppingState extends LiftState {

    //停止状态,开门,那是要的!
    @Override
    public void open() {
        //状态修改
        super.context.setLiftState(Context.OPENING_STATE);
        //动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作
        super.context.getLiftState().open();
    }

    @Override
    public void close() {//虽然可以关门,但这个动作不归我执行
        //状态修改
        super.context.setLiftState(Context.CLOSING_STATE);
        //动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作
        super.context.getLiftState().close();
    }

    //停止状态再跑起来,正常的很
    @Override
    public void run() {
        //状态修改
        super.context.setLiftState(Context.RUNNING_STATE);
        //动作委托为CloseState来执行,也就是委托给了ClosingState子类执行这个动作
        super.context.getLiftState().run();
    }

    //停止状态是怎么发生的呢?当然是停止方法执行了
    @Override
    public void stop() {
        System.out.println("电梯停止了...");
    }
}
java
public class Context {
    public final static OpeningState OPENING_STATE = new OpeningState();

    public final static ClosingState CLOSING_STATE = new ClosingState();

    public final static RunningState RUNNING_STATE = new RunningState();

    public final static StoppingState STOPPING_STATE = new StoppingState();

    private LiftState liftState;

    public LiftState getLiftState() {
        return liftState;
    }

    public void setLiftState(LiftState liftState) {
        this.liftState = liftState;
        this.liftState.setContext(this);
    }

    public void open() {
        liftState.open();
    }
    public void close() {
        liftState.close();
    }
    public void run() {
        liftState.run();
    }

    public void stop() {
        liftState.stop();
    }
}
java
public class Client {
    public static void main(String[] args) {
        Context context = new Context();

        context.setLiftState(new RunningState());

        context.open();
        context.close();
        context.stop();
        context.run();
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <memory>

// 前置声明
class ClosingState;
class OpeningState;
class RunningState;
class StoppingState;

// 上下文
class Context {
public:
    // 使用 std::shared_ptr 管理状态对象
    static std::shared_ptr<OpeningState> OPENING_STATE;
    static std::shared_ptr<ClosingState> CLOSING_STATE;
    static std::shared_ptr<RunningState> RUNNING_STATE;
    static std::shared_ptr<StoppingState> STOPPING_STATE;

private:
    std::shared_ptr<LiftState> liftState;

public:
    std::shared_ptr<LiftState> getLiftState() const {
        return liftState;
    }

    void setLiftState(std::shared_ptr<LiftState> liftState) {
        this->liftState = liftState;
        if (this->liftState) {
            this->liftState->setContext(this);
        }
    }

    void open() {
        liftState->open();
    }

    void close() {
        liftState->close();
    }

    void run() {
        liftState->run();
    }

    void stop() {
        liftState->stop();
    }
};

// 抽象状态
class LiftState {
protected:
    std::shared_ptr<Context> context;

public:
    void setContext(std::shared_ptr<Context> context) {
        this->context = context;
    }

    virtual void open() = 0;
    virtual void close() = 0;
    virtual void run() = 0;
    virtual void stop() = 0;
    virtual ~LiftState() = default; // 虚析构函数
};

// 关闭状态
class ClosingState : public LiftState {
public:
    void close() override {
        std::cout << "电梯门关闭..." << std::endl;
    }

    void open() override {
        context->setLiftState(Context::OPENING_STATE);
        context->open();
    }

    void run() override {
        context->setLiftState(Context::RUNNING_STATE);
        context->run();
    }

    void stop() override {
        context->setLiftState(Context::STOPPING_STATE);
        context->stop();
    }
};

// 开启状态
class OpeningState : public LiftState {
public:
    void open() override {
        std::cout << "Opening...." << std::endl;
    }

    void close() override {
        context->setLiftState(Context::CLOSING_STATE);
        context->close();
    }

    void run() override {}

    void stop() override {}
};

// 运行状态
class RunningState : public LiftState {
public:
    void open() override {}

    void close() override {}

    void run() override {
        std::cout << "电梯正在运行..." << std::endl;
    }

    void stop() override {
        context->setLiftState(Context::STOPPING_STATE);
        context->stop();
    }
};

// 停止状态
class StoppingState : public LiftState {
public:
    void open() override {
        context->setLiftState(Context::OPENING_STATE);
        context->open();
    }

    void close() override {
        context->setLiftState(Context::CLOSING_STATE);
        context->close();
    }

    void run() override {
        context->setLiftState(Context::RUNNING_STATE);
        context->run();
    }

    void stop() override {
        std::cout << "电梯停止了..." << std::endl;
    }
};

// 静态成员初始化
std::shared_ptr<OpeningState> Context::OPENING_STATE = std::make_shared<OpeningState>();
std::shared_ptr<ClosingState> Context::CLOSING_STATE = std::make_shared<ClosingState>();
std::shared_ptr<RunningState> Context::RUNNING_STATE = std::make_shared<RunningState>();
std::shared_ptr<StoppingState> Context::STOPPING_STATE = std::make_shared<StoppingState>();

int main() {
    auto context = std::make_shared<Context>();
    context->setLiftState(Context::RUNNING_STATE); // 使用静态成员

    context->open();
    context->close();
    context->stop();
    context->run();

    return 0;
}

策略模式(Strategy)

定义一系列的算法,将每一个算法封装起来,并让它们可以互换。符合开放封闭原则依赖倒置原则

优点:

  • 由于策略类都实现同一个接口,所以使它们之间可以自由切换。 易于扩展
  • 增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合开闭原则
  • 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

使用场景

  • 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。

  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。

  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。

  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。

  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

  • Java代码演示

java
public interface Strategy {
    void show();
}
public class StrategyA implements Strategy{
    @Override
    public void show() {
        System.out.println("买1送1");
    }
}
public class StrategyB implements Strategy{
    @Override
    public void show() {
        System.out.println("满200减50");
    }
}
public class StrategyC implements Strategy{
    @Override
    public void show() {
        System.out.println("满1000元加一元换购任意200元以下商品");
    }
}
java
public class SalesMan {
    //聚合策略类对象
    private Strategy strategy;

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

    public void salesManShow() {
        strategy.show();
    }

    public Strategy getStrategy() {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
}
java
public class Client {
    public static void main(String[] args) {
        SalesMan salesMan = new SalesMan(new StrategyA());

        salesMan.salesManShow();

        System.out.println("======================");

        salesMan.setStrategy(new StrategyB());
        salesMan.salesManShow();
        System.out.println("======================");

        salesMan.setStrategy(new StrategyC());
        salesMan.salesManShow();
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <memory>

// 策略接口
class Strategy {
public:
    virtual void show() = 0;
    virtual ~Strategy() = default; // 虚析构函数
};

// 策略A
class StrategyA : public Strategy {
public:
    void show() override {
        std::cout << "买1送1" << std::endl;
    }
};

// 策略B
class StrategyB : public Strategy {
public:
    void show() override {
        std::cout << "满200减50" << std::endl;
    }
};

// 策略C
class StrategyC : public Strategy {
public:
    void show() override {
        std::cout << "满1000元加一元换购任意200元以下商品" << std::endl;
    }
};

// 销售员
class SalesMan {
private:
    std::shared_ptr<Strategy> strategy; // 使用 shared_ptr

public:
    SalesMan(std::shared_ptr<Strategy> strategy) : strategy(strategy) {}

    void salesManShow() {
        strategy->show();
    }

    std::shared_ptr<Strategy> getStrategy() const {
        return strategy;
    }

    void setStrategy(std::shared_ptr<Strategy> strategy) {
        this->strategy = strategy;
    }
};

int main() {
    auto salesMan = std::make_shared<SalesMan>(std::make_shared<StrategyA>()); // 使用 make_shared

    salesMan->salesManShow();

    std::cout << "======================" << std::endl;

    salesMan->setStrategy(std::make_shared<StrategyB>()); // 使用 make_shared
    salesMan->salesManShow();
    std::cout << "======================" << std::endl;

    salesMan->setStrategy(std::make_shared<StrategyC>()); // 使用 make_shared
    salesMan->salesManShow();

    return 0;
}

模板方法模式(Template Method**)

在一个方法中定义一个算法的框架,将一些步骤的实现延迟到子类中。符合开放封闭原则里氏替换原则

优点:

  • 将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中。 实现了反向控制
  • 通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 ,并符合开闭原则

缺点

  • 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

适用场景

  • 算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。

  • 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

  • Java代码演示

java
public abstract class AbstractClass {

    //算法
    public final void cookProcess() {
        //第一步:倒油
        this.pourOil();
        //第二步:热油
        this.heatOil();
        //第三步:倒蔬菜
        this.pourVegetable();
        //第四步:倒调味料
        this.pourSauce();
        //第五步:翻炒
        this.fry();
    }


    public void pourOil() {
        System.out.println("倒油");
    }

    //第二步:热油是一样的,所以直接实现
    public void heatOil() {
        System.out.println("热油");
    }

    //第三步:倒蔬菜是不一样的(一个下包菜,一个是下菜心)
    public abstract void pourVegetable();

    //第四步:倒调味料是不一样
    public abstract void pourSauce();

    //第五步:翻炒是一样的,所以直接实现
    public void fry(){
        System.out.println("炒啊炒啊炒到熟啊");
    }
}
java
public class ConcreteClass_BaoCai extends AbstractClass{
    @Override
    public void pourVegetable() {
        System.out.println("下锅的蔬菜是包菜");
    }

    @Override
    public void pourSauce() {
        System.out.println("下锅的酱料是辣椒");
    }
}
java
public class ConcreteClass_CaiXin extends AbstractClass {
    @Override
    public void pourVegetable() {
        System.out.println("下锅的蔬菜是菜心");
    }

    @Override
    public void pourSauce() {
        System.out.println("下锅的酱料是蒜蓉");
    }
}
java
public class Client {
    public static void main(String[] args) {
        ConcreteClass_BaoCai baoCai = new ConcreteClass_BaoCai();
        baoCai.cookProcess();
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <memory>

// 抽象类
class AbstractClass {
public:
    // 算法
    void cookProcess() {
        // 第一步:倒油
        pourOil();
        // 第二步:热油
        heatOil();
        // 第三步:倒蔬菜
        pourVegetable();
        // 第四步:倒调味料
        pourSauce();
        // 第五步:翻炒
        fry();
    }

    void pourOil() {
        std::cout << "倒油" << std::endl;
    }

    // 第二步:热油是一样的,所以直接实现
    void heatOil() {
        std::cout << "热油" << std::endl;
    }

    // 第三步:倒蔬菜是不一样的(一个下包菜,一个是下菜心)
    virtual void pourVegetable() = 0;

    // 第四步:倒调味料是不一样
    virtual void pourSauce() = 0;

    // 第五步:翻炒是一样的,所以直接实现
    void fry() {
        std::cout << "炒啊炒啊炒到熟啊" << std::endl;
    }
    virtual ~AbstractClass() = default; // 虚析构函数
};

// 具体类 - 包菜
class ConcreteClass_BaoCai : public AbstractClass {
public:
    void pourVegetable() override {
        std::cout << "下锅的蔬菜是包菜" << std::endl;
    }

    void pourSauce() override {
        std::cout << "下锅的酱料是辣椒" << std::endl;
    }
};

// 具体类 - 菜心
class ConcreteClass_CaiXin : public AbstractClass {
public:
    void pourVegetable() override {
        std::cout << "下锅的蔬菜是菜心" << std::endl;
    }

    void pourSauce() override {
        std::cout << "下锅的酱料是蒜蓉" << std::endl;
    }
};

int main() {
    std::shared_ptr<AbstractClass> baoCai = std::make_shared<ConcreteClass_BaoCai>();
    baoCai->cookProcess();

    return 0;
}

访问者模式(Visitor)

表示一个作用于某对象结构中的各元素的操作,能够在不改变各元素类的前提下定义作用于这些元素的新操作。符合单一职责原则

优点:

  • 在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  • 通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
  • 通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。

缺点:

  • 在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了开闭原则
  • 访问者模式依赖了具体类,而没有依赖抽象类。

使用场景

  • 对象结构相对稳定,但其操作算法经常变化的程序。
  • 对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。

扩展访问者模式用到了一种双分派的技术。

  • 分派 变量被声明时的类型叫做变量的静态类型,有些人又把静态类型叫做明显类型;而变量所引用的对象的真实类型又叫做变量的实际类型。比如 Map map = new HashMap() ,map变量的静态类型是 Map ,实际类型是 HashMap 。根据对象的类型而对方法进行的选择,就是分派(Dispatch),分派(Dispatch)又分为两种,即静态分派和动态分派。

  • 静态分派(Static Dispatch) 发生在编译时期,分派根据静态类型信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。

  • 动态分派(Dynamic Dispatch) 发生在运行时期,动态分派动态地置换掉某个方法。Java通过方法的重写支持动态分派。

  • 双分派 所谓双分派技术就是在选择一个方法的时候,不仅仅要根据消息接收者(receiver)的运行时区别,还要根据参数的运行时区别。

  • Java代码演示

java
// 1. 定义访问者接口
interface ShapeVisitor {
    void visit(Rectangle rectangle);
    void visit(Circle circle);
    void visit(Triangle triangle);
}

// 2. 定义元素接口
interface Shape {
    void accept(ShapeVisitor visitor);
}

// 3. 具体元素类(Rectangle)
class Rectangle implements Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    public double getWidth() {
        return width;
    }

    public double getHeight() {
        return height;
    }

    @Override
    public void accept(ShapeVisitor visitor) {
        visitor.visit(this);
    }
}

// 4. 具体元素类(Circle)
class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    @Override
    public void accept(ShapeVisitor visitor) {
        visitor.visit(this);
    }
}

// 5. 具体元素类(Triangle)
class Triangle implements Shape {
    private double base;
    private double height;

    public Triangle(double base, double height) {
        this.base = base;
        this.height = height;
    }

    public double getBase() {
        return base;
    }

    public double getHeight() {
        return height;
    }

    @Override
    public void accept(ShapeVisitor visitor) {
        visitor.visit(this);
    }
}

// 6. 具体访问者类(计算面积)
class AreaVisitor implements ShapeVisitor {
    @Override
    public void visit(Rectangle rectangle) {
        double area = rectangle.getWidth() * rectangle.getHeight();
        System.out.println("Rectangle area: " + area);
    }

    @Override
    public void visit(Circle circle) {
        double area = Math.PI * circle.getRadius() * circle.getRadius();
        System.out.println("Circle area: " + area);
    }

    @Override
    public void visit(Triangle triangle) {
        double area = 0.5 * triangle.getBase() * triangle.getHeight();
        System.out.println("Triangle area: " + area);
    }
}

// 7. 具体访问者类(绘制图形)
class DrawVisitor implements ShapeVisitor {
    @Override
    public void visit(Rectangle rectangle) {
        System.out.println("Drawing Rectangle with width " + rectangle.getWidth() + " and height " + rectangle.getHeight());
    }

    @Override
    public void visit(Circle circle) {
        System.out.println("Drawing Circle with radius " + circle.getRadius());
    }

    @Override
    public void visit(Triangle triangle) {
        System.out.println("Drawing Triangle with base " + triangle.getBase() + " and height " + triangle.getHeight());
    }
}

// 8. 客户端代码
public class VisitorPatternDemo {
    public static void main(String[] args) {
        Shape rectangle = new Rectangle(5, 10);
        Shape circle = new Circle(7);
        Shape triangle = new Triangle(6, 8);

        ShapeVisitor areaVisitor = new AreaVisitor();
        ShapeVisitor drawVisitor = new DrawVisitor();

        // 访问元素并执行操作
        rectangle.accept(areaVisitor);
        circle.accept(areaVisitor);
        triangle.accept(areaVisitor);

        rectangle.accept(drawVisitor);
        circle.accept(drawVisitor);
        triangle.accept(drawVisitor);
    }
}
  • Cpp代码演示
cpp
#include <iostream>
#include <cmath>
#include <vector>

// 1. 定义访问者接口
class Shape;

class ShapeVisitor {
public:
    virtual void visit(class Rectangle& rectangle) = 0;
    virtual void visit(class Circle& circle) = 0;
    virtual void visit(class Triangle& triangle) = 0;
};

// 2. 定义元素接口
class Shape {
public:
    virtual void accept(ShapeVisitor& visitor) = 0;
    virtual ~Shape() = default;
};

// 3. 具体元素类(Rectangle)
class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    double getWidth() const { return width; }
    double getHeight() const { return height; }

    void accept(ShapeVisitor& visitor) override {
        visitor.visit(*this);
    }
};

// 4. 具体元素类(Circle)
class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    double getRadius() const { return radius; }

    void accept(ShapeVisitor& visitor) override {
        visitor.visit(*this);
    }
};

// 5. 具体元素类(Triangle)
class Triangle : public Shape {
private:
    double base;
    double height;

public:
    Triangle(double b, double h) : base(b), height(h) {}

    double getBase() const { return base; }
    double getHeight() const { return height; }

    void accept(ShapeVisitor& visitor) override {
        visitor.visit(*this);
    }
};

// 6. 具体访问者类(计算面积)
class AreaVisitor : public ShapeVisitor {
public:
    void visit(Rectangle& rectangle) override {
        double area = rectangle.getWidth() * rectangle.getHeight();
        std::cout << "Rectangle area: " << area << std::endl;
    }

    void visit(Circle& circle) override {
        double area = M_PI * circle.getRadius() * circle.getRadius();
        std::cout << "Circle area: " << area << std::endl;
    }

    void visit(Triangle& triangle) override {
        double area = 0.5 * triangle.getBase() * triangle.getHeight();
        std::cout << "Triangle area: " << area << std::endl;
    }
};

// 7. 具体访问者类(绘制图形)
class DrawVisitor : public ShapeVisitor {
public:
    void visit(Rectangle& rectangle) override {
        std::cout << "Drawing Rectangle with width " << rectangle.getWidth() << " and height " << rectangle.getHeight() << std::endl;
    }

    void visit(Circle& circle) override {
        std::cout << "Drawing Circle with radius " << circle.getRadius() << std::endl;
    }

    void visit(Triangle& triangle) override {
        std::cout << "Drawing Triangle with base " << triangle.getBase() << " and height " << triangle.getHeight() << std::endl;
    }
};

// 8. 客户端代码
int main() {
    std::vector<Shape*> shapes;
    shapes.push_back(new Rectangle(5, 10));
    shapes.push_back(new Circle(7));
    shapes.push_back(new Triangle(6, 8));

    AreaVisitor areaVisitor;
    DrawVisitor drawVisitor;

    // 访问元素并执行操作
    for (auto shape : shapes) {
        shape->accept(areaVisitor);
        shape->accept(drawVisitor);
    }

    // 清理内存
    for (auto shape : shapes) {
        delete shape;
    }

    return 0;
}