设计模式总结(四)

上一篇总结了设计模式的结构型, 接下来总结一下设计模式的几种行为型模式。

模板方法模式:

模板方法模式定义了一个算法的骨架,将一些步骤延迟到子类中实现。这样做的目的是使得子类可以在不改变算法结构的情况下重新定义算法的某些步骤,从而实现算法的复用和定制化。

模板方法模式通常包含以下角色:

  1. 抽象类(Abstract Class):定义了一个模板方法,其中包含算法的骨架以及一系列抽象方法,这些抽象方法由子类去实现。

  2. 具体子类(Concrete Class):实现了抽象类中定义的抽象方法,从而完成算法的特定步骤。

下面是一个使用模板方法模式的示例:

#include <iostream>// 抽象类
class AbstractClass {
public:// 模板方法void templateMethod() {// 调用具体方法stepOne();stepTwo();stepThree();}// 抽象方法,由子类实现virtual void stepOne() = 0;virtual void stepTwo() = 0;virtual void stepThree() = 0;
};// 具体子类 A
class ConcreteClassA : public AbstractClass {
public:void stepOne() override {std::cout << "ConcreteClassA: Step One\n";}void stepTwo() override {std::cout << "ConcreteClassA: Step Two\n";}void stepThree() override {std::cout << "ConcreteClassA: Step Three\n";}
};// 具体子类 B
class ConcreteClassB : public AbstractClass {
public:void stepOne() override {std::cout << "ConcreteClassB: Step One\n";}void stepTwo() override {std::cout << "ConcreteClassB: Step Two\n";}void stepThree() override {std::cout << "ConcreteClassB: Step Three\n";}
};int main() {AbstractClass* objectA = new ConcreteClassA();AbstractClass* objectB = new ConcreteClassB();// 调用模板方法objectA->templateMethod();objectB->templateMethod();delete objectA;delete objectB;return 0;
}

在上面的示例中,AbstractClass 是一个抽象类,其中定义了模板方法 templateMethod(),以及三个抽象方法 stepOne()stepTwo()stepThree()ConcreteClassAConcreteClassB 是具体子类,分别实现了这三个抽象方法。

main() 函数中,我们创建了 ConcreteClassAConcreteClassB 的实例,并分别调用它们的 templateMethod() 方法,从而演示了模板方法模式的使用。输出结果会显示具体子类中实现的步骤被正确调用。

观察者模式:

观察者模式义了一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。观察者模式也被称为发布-订阅(Publish-Subscribe)模式。

观察者模式通常包含以下角色:

  1. 主题(Subject):也称为被观察者或可观察对象,它维护了一个观察者列表,并提供了添加、删除和通知观察者的方法。

  2. 观察者(Observer):定义了一个更新接口,使得在主题状态变化时能够接收到通知并进行相应的更新操作。

  3. 具体主题(Concrete Subject):是主题的具体实现,负责维护状态并在状态变化时通知观察者。

  4. 具体观察者(Concrete Observer):实现了观察者接口,当接收到主题的通知时进行相应的更新操作。

观察者模式的优点包括降低了主题和观察者之间的耦合度,使得主题和观察者可以独立变化;同时也支持广播通知,多个观察者可以同时监听同一个主题。

下面是一个简单的 C++ 示例,演示了观察者模式的实现:

#include <iostream>
#include <vector>// 观察者接口
class Observer {
public:virtual void update(const std::string& message) = 0;
};// 具体观察者 A
class ConcreteObserverA : public Observer {
public:void update(const std::string& message) override {std::cout << "ConcreteObserverA received message: " << message << std::endl;}
};// 具体观察者 B
class ConcreteObserverB : public Observer {
public:void update(const std::string& message) override {std::cout << "ConcreteObserverB received message: " << message << std::endl;}
};// 主题接口
class Subject {
public:virtual void attach(Observer* observer) = 0;virtual void detach(Observer* observer) = 0;virtual void notify(const std::string& message) = 0;
};// 具体主题
class ConcreteSubject : public Subject {
private:std::vector<Observer*> observers;public:void attach(Observer* observer) override {observers.push_back(observer);}void detach(Observer* observer) override {for (auto it = observers.begin(); it != observers.end(); ++it) {if (*it == observer) {observers.erase(it);break;}}}void notify(const std::string& message) override {for (auto observer : observers) {observer->update(message);}}void changeState(const std::string& newState) {notify(newState);}
};int main() {ConcreteObserverA observerA;ConcreteObserverB observerB;ConcreteSubject subject;subject.attach(&observerA);subject.attach(&observerB);subject.changeState("New State");subject.detach(&observerA);subject.changeState("Another State");return 0;
}

在上面的示例中,我们定义了观察者模式中的观察者接口 Observer 和主题接口 Subject,并实现了具体的观察者类 ConcreteObserverAConcreteObserverB,以及具体的主题类 ConcreteSubject

main() 函数中,我们创建了两个具体的观察者对象 observerAobserverB,并将它们注册到具体主题对象 subject 中。然后我们调用 subjectchangeState() 方法改变主题的状态,并观察到具体观察者接收到了相应的通知并进行了更新操作。最后我们将 observerA 从主题中解除注册,并再次改变主题的状态,观察到只有 observerB 接收到了通知。

策略模式:

策略模式定义了一系列算法,并将每个算法封装起来,使得它们可以互相替换,使得算法的变化不会影响到使用算法的客户端。策略模式也被称为政策模式。

策略模式通常包含以下角色:

  1. 环境类(Context):维护一个对策略对象的引用,并在需要时调用策略对象的方法。

  2. 策略接口(Strategy Interface):定义了策略族的通用接口,通常包含一个或多个方法用于执行具体的算法。

  3. 具体策略类(Concrete Strategy):实现了策略接口,提供了具体的算法实现。

策略模式的优点包括将算法的实现与使用算法的客户端解耦,使得算法可以独立变化而不影响客户端代码;同时也支持运行时动态地选择和切换算法。

下面是一个简单的 C++ 示例,演示了策略模式的实现:

#include <iostream>// 策略接口
class Strategy {
public:virtual void execute() = 0;
};// 具体策略类 A
class ConcreteStrategyA : public Strategy {
public:void execute() override {std::cout << "Executing ConcreteStrategyA\n";}
};// 具体策略类 B
class ConcreteStrategyB : public Strategy {
public:void execute() override {std::cout << "Executing ConcreteStrategyB\n";}
};// 环境类
class Context {
private:Strategy* strategy;public:Context(Strategy* strategy) : strategy(strategy) {}void setStrategy(Strategy* strategy) {this->strategy = strategy;}void executeStrategy() {if (strategy) {strategy->execute();} else {std::cout << "No strategy set\n";}}
};int main() {ConcreteStrategyA strategyA;ConcreteStrategyB strategyB;Context context(&strategyA);context.executeStrategy();context.setStrategy(&strategyB);context.executeStrategy();return 0;
}

在上面的示例中,我们定义了策略模式中的策略接口 Strategy,以及具体的策略类 ConcreteStrategyAConcreteStrategyB,它们实现了策略接口中的 execute() 方法。还定义了环境类 Context,它维护了一个对策略对象的引用,并在需要时调用策略对象的 execute() 方法。

main() 函数中,我们创建了具体的策略对象 strategyAstrategyB,然后分别将它们传递给环境类 context,并调用 contextexecuteStrategy() 方法执行相应的策略。输出结果会显示具体的策略类被正确调用。

责任链模式:

责任链模式通过一系列处理器对象(也称为责任链)来处理请求,每个处理器对象都包含了对请求的处理逻辑,并且知道下一个处理器对象是谁。请求会从链的顶部开始沿着链传递,直到有一个处理器对象能够处理该请求为止。

责任链模式的主要目的是解耦发送者和接收者之间的关系,使得多个对象都有机会处理请求,从而避免将请求的发送者与接收者直接耦合在一起。

责任链模式通常包含以下角色:

  1. 抽象处理器(Handler):定义了一个处理请求的接口,并包含了一个指向下一个处理器的引用。

  2. 具体处理器(Concrete Handler):实现了抽象处理器接口,负责处理具体的请求,如果自己无法处理则将请求传递给下一个处理器。

下面是一个简单的 C++ 示例,演示了责任链模式的实现:

#include <iostream>
#include <string>// 抽象处理器
class Handler {
protected:Handler* successor;public:Handler() : successor(nullptr) {}void setSuccessor(Handler* successor) {this->successor = successor;}virtual void handleRequest(const std::string& request) = 0;
};// 具体处理器 A
class ConcreteHandlerA : public Handler {
public:void handleRequest(const std::string& request) override {if (request == "A") {std::cout << "ConcreteHandlerA handles the request\n";} else if (successor != nullptr) {successor->handleRequest(request);}}
};// 具体处理器 B
class ConcreteHandlerB : public Handler {
public:void handleRequest(const std::string& request) override {if (request == "B") {std::cout << "ConcreteHandlerB handles the request\n";} else if (successor != nullptr) {successor->handleRequest(request);}}
};// 具体处理器 C
class ConcreteHandlerC : public Handler {
public:void handleRequest(const std::string& request) override {if (request == "C") {std::cout << "ConcreteHandlerC handles the request\n";} else if (successor != nullptr) {successor->handleRequest(request);}}
};int main() {ConcreteHandlerA handlerA;ConcreteHandlerB handlerB;ConcreteHandlerC handlerC;handlerA.setSuccessor(&handlerB);handlerB.setSuccessor(&handlerC);handlerA.handleRequest("A");handlerA.handleRequest("B");handlerA.handleRequest("C");handlerA.handleRequest("D");return 0;
}

在上面的示例中,我们定义了责任链模式中的抽象处理器 Handler 和具体的处理器类 ConcreteHandlerAConcreteHandlerBConcreteHandlerC,它们实现了抽象处理器接口中的 handleRequest() 方法。

main() 函数中,我们创建了具体的处理器对象,并通过 setSuccessor() 方法将它们连接成责任链。然后我们调用 handlerAhandleRequest() 方法,并传递不同的请求,观察输出结果可以看到请求会从链的顶部开始传递,直到找到合适的处理器来处理请求为止。

命令模式:

命令模式将请求封装成一个对象,从而使得可以用不同的请求对客户端参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。

命令模式通常包含以下角色:

  1. 命令接口(Command):定义了执行请求的接口,通常包含一个执行方法(execute)。

  2. 具体命令(Concrete Command):实现了命令接口,负责执行具体的请求操作,并包含了接收者对象的引用。

  3. 调用者(Control):负责调用命令对象执行请求。

下面是一个简单的 C++ 示例,演示了命令模式的实现:

#include <iostream>
#include <vector>// 定义一个命令接口
class Command {
public:virtual void execute() = 0;
};// 具体命令类
class LightOnCommand : public Command {
public:void execute() override {std::cout << "Light is on" << std::endl;}
};class LightOffCommand : public Command {
public:void execute() override {std::cout << "Light is off" << std::endl;}
};// 调用者类
class RemoteControl {
private:std::vector<Command*> commands;public:void addCommand(Command* command) {commands.push_back(command);}void pressButton(int index) {if (index >= 0 && index < commands.size()) {commands[index]->execute();}}
};int main() {RemoteControl remote;// 创建命令Command* lightOn = new LightOnCommand();Command* lightOff = new LightOffCommand();// 添加命令到遥控器remote.addCommand(lightOn);remote.addCommand(lightOff);// 执行命令remote.pressButton(0);remote.pressButton(1);return 0;
}

在这个示例中,我们定义了一个Command接口,然后实现了两个具体的命令类LightOnCommandLightOffCommand。然后我们创建了一个RemoteControl类,它可以添加命令并执行。在main函数中,我们演示了如何使用这个简单的命令模式来控制灯的开关。

状态模式:

状态模式允许一个对象在其内部状态改变时改变其行为。状态模式的关键在于定义了一系列表示不同状态的对象,并将这些状态对象封装成独立的类,使得状态的改变可以通过改变状态对象来实现,从而使得对象的行为在不同状态下有所不同。

状态模式通常包含以下角色:

  1. 环境类(Context):定义了客户端感兴趣的接口,并维护了一个当前状态对象的引用。

  2. 抽象状态类(State):定义了一个接口用于封装与环境对象的一个特定状态相关的行为。

  3. 具体状态类(Concrete State):实现了抽象状态类中定义的接口,负责处理环境对象在当前状态下的行为。

下面是一个简单的 C++ 示例,演示了状态模式的实现:

#include <iostream>
#include <string>// 环境类
class Context;// 抽象状态类
class State {
public:virtual void handle(Context* context) = 0;
};// 具体状态类 A
class ConcreteStateA : public State {
public:void handle(Context* context) override;
};// 具体状态类 B
class ConcreteStateB : public State {
public:void handle(Context* context) override;
};// 环境类
class Context {
private:State* state;public:Context() : state(nullptr) {}void setState(State* newState) {state = newState;}void request() {if (state) {state->handle(this);} else {std::cout << "No state set\n";}}
};void ConcreteStateA::handle(Context* context) {std::cout << "ConcreteStateA handles the request\n";context->setState(new ConcreteStateB());  // 切换到具体状态类 B
}void ConcreteStateB::handle(Context* context) {std::cout << "ConcreteStateB handles the request\n";context->setState(new ConcreteStateA());  // 切换到具体状态类 A
}int main() {Context context;context.request();  // 输出 "No state set"context.setState(new ConcreteStateA());context.request();  // 输出 "ConcreteStateA handles the request"context.request();  // 输出 "ConcreteStateB handles the request"return 0;
}

在上面的示例中,我们定义了状态模式中的环境类 Context、抽象状态类 State 和具体状态类 ConcreteStateAConcreteStateB

main() 函数中,我们创建了环境对象 context,并设置了初始状态为具体状态类 A。然后我们调用环境对象的 request() 方法,观察输出结果可以看到环境对象根据当前状态的不同而执行了不同的行为,并且可以动态地切换状态。

访问者模式:

访问者模式可以在不修改现有类的前提下,通过为现有类添加新的访问者(Visitor)类来实现对现有类功能的扩展。访问者模式的核心思想是将数据结构与数据操作分离,使得数据结构和数据操作可以独立变化。

访问者模式通常包含以下角色:

  1. 抽象访问者(Visitor):定义了对每个具体元素类的访问行为,通常包含一个访问方法用于接收具体元素类的实例。

  2. 具体访问者(Concrete Visitor):实现了抽象访问者中定义的访问方法,负责实现对具体元素类的不同访问操作。

  3. 抽象元素(Element):定义了一个接受访问者对象的接口,通常包含一个接受方法用于接收访问者对象。

  4. 具体元素(Concrete Element):实现了抽象元素中定义的接受方法,负责接受访问者对象并调用访问者对象的访问方法。

  5. 对象结构(Object Structure):用于存储具体元素对象,并提供接口让访问者访问其中的元素。

下面是一个简单的 C++ 示例,演示了访问者模式的实现:

#include <iostream>
#include <vector>// 前向声明
class ConcreteElementA;
class ConcreteElementB;// 抽象访问者
class Visitor {
public:virtual void visitConcreteElementA(ConcreteElementA* element) = 0;virtual void visitConcreteElementB(ConcreteElementB* element) = 0;
};// 具体访问者 A
class ConcreteVisitorA : public Visitor {
public:void visitConcreteElementA(ConcreteElementA* element) override {std::cout << "ConcreteVisitorA visited ConcreteElementA\n";}void visitConcreteElementB(ConcreteElementB* element) override {std::cout << "ConcreteVisitorA visited ConcreteElementB\n";}
};// 具体访问者 B
class ConcreteVisitorB : public Visitor {
public:void visitConcreteElementA(ConcreteElementA* element) override {std::cout << "ConcreteVisitorB visited ConcreteElementA\n";}void visitConcreteElementB(ConcreteElementB* element) override {std::cout << "ConcreteVisitorB visited ConcreteElementB\n";}
};// 抽象元素
class Element {
public:virtual void accept(Visitor* visitor) = 0;
};// 具体元素 A
class ConcreteElementA : public Element {
public:void accept(Visitor* visitor) override {visitor->visitConcreteElementA(this);}
};// 具体元素 B
class ConcreteElementB : public Element {
public:void accept(Visitor* visitor) override {visitor->visitConcreteElementB(this);}
};// 对象结构
class ObjectStructure {
private:std::vector<Element*> elements;public:void addElement(Element* element) {elements.push_back(element);}void accept(Visitor* visitor) {for (Element* element : elements) {element->accept(visitor);}}
};int main() {ConcreteElementA elementA;ConcreteElementB elementB;ObjectStructure objectStructure;objectStructure.addElement(&elementA);objectStructure.addElement(&elementB);ConcreteVisitorA visitorA;ConcreteVisitorB visitorB;objectStructure.accept(&visitorA);objectStructure.accept(&visitorB);return 0;
}

在上面的示例中,我们定义了访问者模式中的抽象访问者 Visitor 和具体访问者类 ConcreteVisitorAConcreteVisitorB,以及抽象元素类 Element 和具体元素类 ConcreteElementAConcreteElementB

我们还定义了对象结构类 ObjectStructure,用于存储具体元素对象,并提供接口让访问者访问其中的元素。

main() 函数中,我们创建了具体的元素对象 elementAelementB,并添加到对象结构中。然后我们创建了具体的访问者对象 visitorAvisitorB,并通过对象结构的 accept() 方法让访问者访问其中的元素。观察输出结果可以看到不同的访问者对象对不同的元素对象执行了不同的访问操作。

迭代器模式:

迭代器模式提供一种顺序访问集合对象元素的方法,而不暴露集合对象的内部表示。迭代器模式使得可以访问一个聚合对象的元素而无需暴露其内部结构。

迭代器模式通常包含以下角色:

  1. 迭代器接口(Iterator):定义了迭代器的通用操作,例如获取下一个元素、判断是否还有下一个元素等。

  2. 具体迭代器(Concrete Iterator):实现了迭代器接口,负责对具体的集合对象进行迭代操作,并记录迭代的当前位置。

  3. 聚合接口(Aggregate):定义了创建迭代器对象的接口,通常包含一个获取迭代器的方法。

  4. 具体聚合类(Concrete Aggregate):实现了聚合接口,负责创建具体迭代器对象,并提供了一种方法让客户端可以访问集合对象的元素。

下面是一个简单的 C++ 示例,演示了迭代器模式的实现:

#include <iostream>
#include <vector>// 迭代器接口
template<typename T>
class Iterator {
public:virtual bool hasNext() const = 0;virtual T next() = 0;
};// 具体迭代器
template<typename T>
class ConcreteIterator : public Iterator<T> {
private:std::vector<T> data;size_t position;public:ConcreteIterator(const std::vector<T>& elements) : data(elements), position(0) {}bool hasNext() const override {return position < data.size();}T next() override {if (hasNext()) {return data[position++];} else {throw std::out_of_range("Iterator has reached the end");}}
};// 聚合接口
template<typename T>
class Aggregate {
public:virtual Iterator<T>* createIterator() = 0;
};// 具体聚合类
template<typename T>
class ConcreteAggregate : public Aggregate<T> {
private:std::vector<T> elements;public:void addElement(const T& element) {elements.push_back(element);}Iterator<T>* createIterator() override {return new ConcreteIterator<T>(elements);}
};int main() {ConcreteAggregate<int> aggregate;aggregate.addElement(1);aggregate.addElement(2);aggregate.addElement(3);Iterator<int>* iterator = aggregate.createIterator();while (iterator->hasNext()) {std::cout << iterator->next() << " ";}std::cout << std::endl;delete iterator;return 0;
}

在上面的示例中,我们定义了迭代器模式中的迭代器接口 Iterator 和具体迭代器类 ConcreteIterator,以及聚合接口 Aggregate 和具体聚合类 ConcreteAggregate

main() 函数中,我们创建了具体聚合对象 aggregate,并添加了一些元素。然后我们通过聚合对象的 createIterator() 方法创建了迭代器对象 iterator,并使用迭代器对象遍历了集合对象的元素并输出。最后别忘了释放迭代器对象的内存空间,以避免内存泄漏。

备忘录模式:

备忘录模式允许在不破坏封装性的前提下捕获对象的内部状态,并在对象之外保存这个状态,从而在需要时可以将对象恢复到之前的状态。备忘录模式的关键在于将对象的状态保存到一个备忘录对象中,并提供了一种方法来恢复对象的状态。

备忘录模式通常包含以下角色:

  1. 发起人(Originator):负责创建备忘录对象,并可以使用备忘录对象来恢复自身的状态。

  2. 备忘录(Memento):负责存储发起人对象的内部状态,可以包含多个状态属性。

  3. 负责人(Caretaker):负责保存备忘录对象,但不对备忘录对象进行操作,只负责存储和获取备忘录。

下面是一个简单的 C++ 示例,演示了备忘录模式的实现:

#include <iostream>
#include <string>// 备忘录类
class Memento {
private:std::string state;public:Memento(const std::string& s) : state(s) {}const std::string& getState() const {return state;}
};// 发起人类
class Originator {
private:std::string state;public:void setState(const std::string& s) {std::cout << "Setting state to: " << s << std::endl;state = s;}Memento* createMemento() {return new Memento(state);}void restoreFromMemento(const Memento* memento) {state = memento->getState();std::cout << "Restored state to: " << state << std::endl;}
};// 负责人类
class Caretaker {
private:Memento* memento;public:void setMemento(Memento* m) {memento = m;}Memento* getMemento() const {return memento;}
};int main() {Originator originator;Caretaker caretaker;originator.setState("State 1");caretaker.setMemento(originator.createMemento());originator.setState("State 2");originator.restoreFromMemento(caretaker.getMemento());return 0;
}

在上面的示例中,我们定义了备忘录模式中的备忘录类 Memento、发起人类 Originator 和负责人类 Caretaker

main() 函数中,我们创建了发起人对象 originator 和负责人对象 caretaker。首先我们通过发起人对象的 setState() 方法设置了状态为 "State 1",然后通过负责人对象的 setMemento() 方法保存了当前状态的备忘录。接着我们再次通过发起人对象的 setState() 方法设置了状态为 "State 2",然后通过发起人对象的 restoreFromMemento() 方法将状态恢复到之前保存的备忘录的状态,输出结果显示成功恢复到了之前保存的状态。

中介者模式:

中介者模式允许对象之间通过一个中介者对象进行交互,从而减少对象之间的直接耦合。中介者模式的核心思想是将对象之间的通信和交互行为封装到一个中介者对象中,使得对象之间不需要直接相互引用,而是通过中介者对象来进行通信。

中介者模式通常包含以下角色:

  1. 中介者(Mediator):定义了一个接口用于与各个同事对象进行通信,并维护了对各个同事对象的引用。

  2. 具体中介者(Concrete Mediator):实现了中介者接口,负责实现各个同事对象之间的协调和通信。

  3. 同事类(Colleague):定义了一个接口用于与中介者对象进行通信,并保存了对中介者对象的引用。

  4. 具体同事类(Concrete Colleague):实现了同事接口,负责实现自身的业务逻辑,并通过中介者对象与其他同事对象进行通信。

下面是一个简单的 C++ 示例,演示了中介者模式的实现:

#include <iostream>
#include <string>// 中介者接口
class Mediator {
public:virtual void sendMessage(const std::string& message, class Colleague* colleague) const = 0;
};// 具体中介者
class ConcreteMediator : public Mediator {
public:void sendMessage(const std::string& message, class Colleague* colleague) const override;
};// 同事类接口
class Colleague {
protected:Mediator* mediator;public:Colleague(Mediator* mediator) : mediator(mediator) {}virtual void send(const std::string& message) = 0;virtual void receive(const std::string& message) = 0;
};// 具体同事类 A
class ConcreteColleagueA : public Colleague {
public:ConcreteColleagueA(Mediator* mediator) : Colleague(mediator) {}void send(const std::string& message) override {mediator->sendMessage(message, this);}void receive(const std::string& message) override {std::cout << "ConcreteColleagueA received message: " << message << std::endl;}
};// 具体同事类 B
class ConcreteColleagueB : public Colleague {
public:ConcreteColleagueB(Mediator* mediator) : Colleague(mediator) {}void send(const std::string& message) override {mediator->sendMessage(message, this);}void receive(const std::string& message) override {std::cout << "ConcreteColleagueB received message: " << message << std::endl;}
};void ConcreteMediator::sendMessage(const std::string& message, Colleague* colleague) const {if (colleague == nullptr) {std::cout << "Colleague is not registered with the mediator\n";return;}if (dynamic_cast<ConcreteColleagueA*>(colleague) != nullptr) {colleague->receive("Message from ConcreteMediator: " + message);} else if (dynamic_cast<ConcreteColleagueB*>(colleague) != nullptr) {colleague->receive("Message from ConcreteMediator: " + message);} else {std::cout << "Unknown colleague type\n";}
}int main() {ConcreteMediator mediator;ConcreteColleagueA colleagueA(&mediator);ConcreteColleagueB colleagueB(&mediator);colleagueA.send("Hello from Colleague A");colleagueB.send("Hi from Colleague B");return 0;
}

在上面的示例中,我们定义了中介者模式中的中介者接口 Mediator 和具体中介者类 ConcreteMediator,以及同事类接口 Colleague 和具体同事类 ConcreteColleagueAConcreteColleagueB

main() 函数中,我们创建了具体中介者对象 mediator 和具体同事对象 colleagueAcolleagueB,并通过同事对象的 send() 方法发送消息,中介者对象会根据消息的来源调用对应的同事对象的 receive() 方法来处理消息。输出结果会显示消息被正确地发送和接收。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「连载」边缘计算(三十二)03-14:边缘部分源码(源码分析篇)

&#xff08;接上篇&#xff09; EdgeCore之edgemesh 前面对EdgeCore组件的edged、devicetwin、edgehub、eventbus、metamanager功能模块进行了分析&#xff0c;本节对EdgeCore组件的另一个功能模块edgemesh进行剖析。目前&#xff0c;KubeEdge官网没有edgemesh相关介绍&…

Visio 2021专业版密钥下载安装

Visio 2021 专业版是微软公司开发的一款功能强大的流程图制作软件&#xff0c;适用于创建各种类型的图表和流程图&#xff0c;包括&#xff1a; 流程图&#xff1a;用于可视化业务流程、工作流程和系统流程。组织结构图&#xff1a;用于展示组织结构和人员关系。网络图&#x…

算法沉淀——贪心算法四(leetcode真题剖析)

算法沉淀——贪心算法四 01.最长回文串02.增减字符串匹配03.分发饼干04.最优除法 01.最长回文串 题目链接&#xff1a;https://leetcode.cn/problems/longest-palindrome/ 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 …

YOLOV5 改进:修改网络结构--C2f 模块

1、前言 YOLOV5 采用C3模块,类似于残差结构的思想 class C3(nn.Module):# CSP Bottleneck with 3 convolutionsdef __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()c_ = int(c2 * e) #…

一篇文章搞懂vue基础(上)

01._初识vue 初识vue: 1.想让Vue工作&#xff0c;就必须创建一个vue实例&#xff0c;且要传入一个配置对象&#xff1b; 2.root容器里的代码依然符合html规范&#xff0c;只不过混入了一些特殊的vue语法 3.root容器里的代码被称为【Vue模版】 4.Vue实例和容器是一一对应的 5.真…

《1w实盘and大盘基金预测 day8》

昨日预测还行&#xff0c;大盘最低到3054缺口附近&#xff0c;并没有补缺口 &#xff0c;顶住了&#xff0c;震荡向上&#xff0c;评分B。 今天行情是指数涨却赚不到钱&#xff0c;像极了拉指数掩护蓝筹股出货 公众号&#xff1a;JavaHelmet 昨天预测&#xff1a; 3042-305…

大数据开发(Hadoop面试真题)

大数据开发&#xff08;Hadoop面试真题&#xff09; 一、HDFSⅠ、HDFS基础概念和架构1、HDFS的作用2、介绍下HDFS&#xff0c;说下HDFS优缺点&#xff0c;以及使用场景&#xff1f;3、请解释一下Hadoop中NameNode和DataNode的作用。4、请解释一下HDFS架构中NameNode和DataNode之…

一文带你了解MySQL事务特性以及其底层原理

MySQL的事务支持是通过其存储引擎&#xff0c;特别是InnoDB存储引擎来提供的。事务的四大特性&#xff0c;通常被称为ACID属性&#xff0c;分别是原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff0…

Linux中,运行程序,顺便将打印信息存储在Log文件中查看

前言 如题&#xff0c;原本打算在代码中自己写一个类去管理将打印信息收集到log日志中&#xff0c;忽然想到&#xff0c;其实也可以写sh脚本 简单demo1 #!/bin/bash# 启动应用程序 test&#xff0c;并将标准输出和标准错误输出都追加到 log 文件中 ./test >> output.log…

使用 mypy 做 type check

前言 完残&#xff01;&#x1f602;&#xff0c;最近看之前写的 Python 代码老得琢磨这比变量的类型是啥&#xff08;Python 无类型系统xxx&#xff09;&#xff0c;不愧是我写的&#xff01; 看段之前写的实现迭代器模式的代码&#xff1a; # 抽象迭代器类 class Iterator(…

7-7 12-24小时制

题目链接&#xff1a;7-7 12-24小时制 一. 题目 1. 题目 2. 输入输出格式 3. 输入输出样例 4. 限制 二、代码 1. 代码实现 #include <stdio.h>int main(void) {int hour, minute;char *str;if (scanf("%d:%d", &hour, &minute) ! 2) {return -1;}i…

操作系统系列学习——死锁处理

文章目录 前言死锁处理 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划学习操作系统并完成6.0S81&#xff0c;加油&#xff01; 本文总结自B站【哈工大】操作系统 李治军&#xff08;全32讲&#xff09; 老师课程讲的非常好&#xff0c;感谢 【哈工大】操…

如何优惠申请DigiCert证书

DigiCert作为全球知名的数字证书颁发机构&#xff0c;其SSL证书以高度的安全性和信任度广受认可。而JoySSL作为国内优秀的SSL证书服务平台&#xff0c;提供了便捷、高效的证书申请服务&#xff0c;让您能够轻松获取并安装DigiCert SSL证书。接下来&#xff0c;本文将详细介绍如…

pytest相关面试题

pytest是什么&#xff1f;它有什么优点&#xff1f; pytest是一个非常流行的Python测试框架&#xff0c;它具有简洁、易用、高校等优点。他可以帮助测试人员方便地编写和运行测试用例&#xff0c;并且提供了丰富的插件和扩展&#xff0c;支持各种测试需求介绍下pytest常用的库 …

什么情况用@RequestBody、@RequestParm、@PathVariable

1.requestParam(请求参数&#xff09;&#xff1a;使用RequestParam注释将请求参数绑定到控制器中的方法参数。用于从请求访问查询参数值的RequestParam注释。 如下请求URL&#xff1a;http://localhost:8080/springmvc/hello/101?param110&param220 以下是RequestParam注…

腾讯云服务器怎么买省钱?先领券,再下单!

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

网工内推 | 七险一金,上市公司招信息安全工程师,大牛带队

01 启明星辰信息技术集团股份有限公司 招聘岗位&#xff1a;数据安全服务工程师 职责描述&#xff1a; 1、负责数据安全服务项目的管理&#xff0c;统筹组织并协调资源落实项目交付实施; 3、负责数据安全风险评估、数据分类分级、数据安全管理制度、数据安全体系规划等数据安…

企事业单位宣传,三下乡的稿子怎么在学习强国网投稿发稿,价格多少钱?

随着学习强国成为各个企事业单位宣传的重要平台&#xff0c;如何在学习强国上发稿&#xff0c;尤其是三下乡的宣传稿件&#xff0c;成为了各位传媒工作者关注的焦点。在这里&#xff0c;我们要向大家介绍一下媒介多多网发稿平台&#xff0c;为大家提供一个便捷高效的投稿发稿渠…

C#实现俄罗斯方块代码

创建一个基本的俄罗斯方块游戏需要实现以下功能&#xff1a; 游戏区域的绘制&#xff1a;这是放置游戏方块的地方。方块的形状和旋转&#xff1a;俄罗斯方块有7种基本形状&#xff0c;每种形状都可以旋转。方块的移动&#xff1a;方块需要能够左移、右移以及下落。方块的固定&…

STM32相关资料汇总

STM32选型表 STM32手册参考网站 https://www.stmcu.org.cn/