中介模式
中介(Mediator)模式建议,取消彼此独立的组件之间的所有直接通信。这些组件必须通过调用特殊中介对象,以实现间接协作。其结果是,这些组件只依赖于一个中介类,而不是直接把这些组件耦合到一起。
在面向对象的程序设计中,程序通常由许多类组成。这些类之间相互需要交换数据,以实现需要的商务逻辑和计算。然而,随着越来越多的类添加到程序中,这些类之间的通信问题可能变得更加复杂。这使得程序阅读和维护更加困难。因为,任何更改都可能涉及多个类的代码。
中介模式,对象之间的通信被集中在一个中介对象中。对象之间不再直接相互通信,而是通过中介进行通信。这减少了通信对象之间的依赖关系,从而减少了耦合。
中介模式应该满足下列的要求
- 避免一组交互对象之间的紧密耦合。
- 可以独立地改变一组对象之间的交互。
中介模式就是定义一个单独的对象(中介),将对象之间的交互作用,封装在这个中介中。这些对象将它们的交互委托给中介对象,而不是直接交互。
#include <iostream>
#include <string>
#include <map>
#include <memory>
using namespace std;
template <class T> class Mediator;
template <class T>
class Storage {
T value;
T getValue() {
return value;
}
public:
void setValue(Mediator<T> *mediator, string storageName, T value) {
this->value = value;
mediator->notifyObservers(storageName);
}
};
class Observer {
public:
virtual void execute() = 0;
};
class Observer1 : public Observer
{
public:
void execute(){
cout << "observer 1" << endl;
}
};
template <class T>
class Mediator {
private:
map<string, shared_ptr<Storage<T>>> storageMap;
map<string, shared_ptr<Observer>> observers;
public:
void setValue(string storageName, T value) {
auto it = storageMap.find(storageName);
shared_ptr<Storage<T>> st;
if (it == storageMap.end())
{
st = make_shared<Storage<T>>();
storageMap[storageName] = st;
}
else {
st = (it->second);
}
st->setValue(this, storageName, value);
}
T getValue(string storageName) {
Storage<T> st = storageMap.get(storageName);
return st.getValue();
}
void addObserver(string storageName, shared_ptr<Observer> observer) {
observers[storageName] = observer;
}
void notifyObservers(string eventName) {
map<string, shared_ptr<Observer>> ::iterator it;
it = observers.find(eventName);
if (it == observers.end())
return;
shared_ptr<Observer> p = it->second;
cout << it->first << ":";
p->execute();
}
};
int main() {
Mediator<int> mediator;
mediator.setValue("bob", 20);
mediator.setValue("alice", 24);
mediator.setValue("jason", 16);
shared_ptr<Observer1> ob1 = make_shared<Observer1>();
shared_ptr<Observer> obptr = static_cast<shared_ptr<Observer>>(ob1);
mediator.addObserver("bob", obptr);
mediator.setValue("bob", 21);
mediator.setValue("alice", 26);
mediator.addObserver("jason", obptr);
mediator.setValue("jason", 21);
}
输出结果
bob:observer 1
jason:observer 1
观察者模式
观察者模式是一种软件设计模式,在这个模式中,一个对象(称为主体)维护一组依赖项,这些依赖项也被称为观察者,通常,通过调用它们的方法之一,自动通知它们任何状态更改。
它主要用于在“事件驱动”软件设计中,实现分布式事件处理系统。在这些系统中,主体通常被称为“事件流”或“事件流源”,而观察者被称为“事件接收器”。
这种模式非常适合任何进程,在启动时CPU不知道数据输入何时到达,它们是“随机”到达,比如,HTTP 请求、GPIO 数据、来自键盘/鼠标的用户输入都属于这种类型。大多数现代程序设计语言都包含实现观察者模式组件的内置“事件”结构。
大多数“观察者”实现,使用后台线程,监听主体事件。
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Observer {
public:
Observer()=default;
virtual void update(string event)=0;
};
class Observer1 : public Observer {
public:
Observer1()=default;
virtual void update(string event) override
{
cout << "Observer1: " << event << endl;
}
};
class Observer2 : public Observer {
public:
Observer2()=default;
virtual void update(string event) override
{
cout << "Observer2: " << event << endl;
}
};
class EventSource {
private:
vector<Observer *> observers;
void notifyObservers(string event) {
for (auto observer : observers)
observer->update(event);
}
public:
void addObserver(Observer *observer) {
observers.push_back(observer);
}
void deliver_cmd(vector<string> cmds) {
for (auto cmd : cmds) {
notifyObservers(cmd);
}
}
};
int main()
{
shared_ptr<EventSource> eventSource = make_shared<EventSource>();
Observer *ob1 = new Observer1();
eventSource->addObserver(ob1);
Observer *ob2 = new Observer2();
eventSource->addObserver(ob2);
vector<string> v1 = {"start", "pause", "stop"};
eventSource->deliver_cmd(v1);
delete ob1;
delete ob2;
}
输出结果
Observer1: start
Observer2: start
Observer1: pause
Observer2: pause
Observer1: stop
Observer2: stop
代理模式
代理(proxy)模式是一种软件设计模式。代理是一个充当其他事物接口的类。代理可以连接到任何东西:网络连接、内存中的大对象、文件或其他一些昂贵或无法复制的资源。
简而言之,代理是一个包装器或代理对象,客户端通过它来访问幕后的提供真实服务的对象。使用代理可以简单地转发到真实对象,或者可以提供额外的逻辑。
代理可以提供额外的功能,例如提供缓存,或者在调用真实对象上的操作之前,检查先决条件。对于客户端,使用代理对象与使用真实对象类似,因为两者都实现了相同的接口。
#include <iostream>
#include <memory>
#include <map>
using namespace std;
class Image {
public:
virtual void displayImage() = 0;
};
class RealImage : public Image {
private:
string filename;
public:
RealImage(string filen) {
filename = filen;
loadImageFromDisk();
}
void loadImageFromDisk() {
cout << "Loading " << filename << endl;
}
void displayImage() {
cout << "Displaying " << filename << endl;
}
};
class Imagebufs {
public:
static shared_ptr<Imagebufs> m_Inst;
static shared_ptr<Imagebufs> getInstance() {
if (m_Inst == nullptr)
m_Inst = make_shared<Imagebufs>();
return m_Inst;
}
shared_ptr<RealImage> get_realimage(string image)
{
map<string, shared_ptr<RealImage>>::iterator it;
it = imgbufs.find(image);
if (it == imgbufs.end())
return nullptr;
return it->second;
}
void put_realimage(string fn, shared_ptr<RealImage> image)
{
imgbufs[fn] = image;
}
private:
map<string, shared_ptr<RealImage>> imgbufs;
};
shared_ptr<Imagebufs> Imagebufs::m_Inst=nullptr;
class ProxyImage : public Image {
private:
string filename;
shared_ptr<RealImage> image = nullptr;
public:
ProxyImage(string filen) {
filename = filen;
}
void displayImage() {
shared_ptr<Imagebufs> bufs = Imagebufs::getInstance();
image = bufs->get_realimage(filename);
if (image == nullptr) {
image = make_shared<RealImage>(filename);
bufs->put_realimage(filename, image);
}
image->displayImage();
}
};
int main() {
shared_ptr<Image> image1 = make_shared<ProxyImage>("HiRes_10MB_Photo1");
shared_ptr<Image> image2 = make_shared<ProxyImage>("HiRes_10MB_Photo2");
shared_ptr<Image> image3 = make_shared<ProxyImage>("HiRes_10MB_Photo2");
image1->displayImage(); // loading
image1->displayImage(); // no loading
image2->displayImage(); // loading
image2->displayImage(); // no loading
image1->displayImage(); // no loading
image3->displayImage(); // no loading
}
输出结果
Loading HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo2
仆人模式
在软件工程中,仆人(Servant )模式定义一个对象,并将它用于向一组类提供某些功能,而无需在每个类中定义该功能。 仆人是一个类,它的实例(甚至只是类)提供处理所需服务的方法,而仆人为其(或与谁)做某事的对象被视为参数。
我们有几个类表示几何对象(椭圆和三角形)。我们可以在一些画布上绘制这些对象。当我们需要为这些对象提供“移动”方法时,我们可以在每个类中实现这个方法,或者我们可以定义一个接口,在仆人中提供“移动”功能。定义这个接口,是为了确保被服务的对象提供仆人所需行为的方法,以便完成所需的移动功能。
我们定义一个接口“IMovable”,指定被服务的对象都需要实现的方法“getPosition”和“setPosition”。第一个方法获取对象在画布上的位置,第二个方法设置对象的位置,并将其绘制在画布上。
然后我们定义了一个仆人类“MoveServant”,它有两个方法“moveTo(Object, where)”和moveBy(Object, int dx, int dy)。
#include <iostream>
#include <memory>
using namespace std;
class Point {
public:
Point() : x(0), y(0){};
Point(int xv, int yv) : x(xv), y(yv){};
int x;
int y;
};
class IMovable {
public:
virtual void setPosition(Point p)=0;
virtual Point getPosition()=0;
};
class Triangle : public IMovable {
Point position;
public:
Triangle(int x, int y) {
position.x = x;
position.y = y;
}
void setPosition(Point p) {
position = p;
}
Point getPosition() {
return position;
}
};
class Ellipse : public IMovable {
private:
Point p;
public:
Ellipse(int x, int y) {
p.x = x;
p.y = y;
}
void setPosition(Point pv) {
p = pv;
}
Point getPosition() {
return p;
}
};
class MoveServant {
public:
MoveServant()=default;
void moveTo(shared_ptr<IMovable> moved, Point pt){
Point pt2 = moved->getPosition();
cout << "Moving from (" << pt2.x << "," << pt2.y << ") to ("
<< pt.x << "," << pt.y << ")" << endl;
moved->setPosition(pt);
}
void moveBy(shared_ptr<IMovable> moved, int x, int y){
Point pt = moved->getPosition();
cout << "Moving from (" << pt.x << "," << pt.y << ") to ("
<< pt.x + x << "," << pt.y + y << ")" << endl;
moved->setPosition(Point(pt.x + x, pt.y + y));
}
};
int main () {
shared_ptr<MoveServant> servant = make_shared<MoveServant>();
shared_ptr<Triangle> triangle = make_shared<Triangle>(-1,0);
shared_ptr<Ellipse> ellipse = make_shared<Ellipse>(2,5);
servant->moveBy(ellipse, 2, 4);
servant->moveTo(triangle, Point(-4,0));
}
输出结果
Moving from (2,5) to (4,9)
Moving from (-1,0) to (-4,0)