【设计模式】中介者模式、命令模式、访问者模式

1、中介者模式

介绍

在面向对象程序设计时,对象之间的交互和通信是常见的情况,当系统比较小时,对象之间的交互比较少,可以直接将对象之间的交互硬编码到对象中,可是当系统比较大时,对象的通信变得复杂,需要一个专门处理对象交互和通信的类,中介者模式就是将colleague对象之间的通信封装到一个中介者类中单独处理。

何时使用:多个类相互耦合,形成了网状结构,需要将上述网状结构分离为星型结构的时候。

中介者承担了较多的责任,一旦中介者出现问题,整个系统都会收到影响。

请添加图片描述

角色

  • 一个抽象的同事类,拥有一个中介者类的指针,提供对这个指针的设置操作, 提供一个被通知的操作
  • 一个抽象的中介者类,定义了同事对象到中介者对象的接口。
  • 若干个具体的同事类,重写其父类中的函数,每个同事只知道自己的行为,而不了解其他同事的行为,它们都依赖中介者对象。
  • 一个具体的中介者类,重写其父类中的函数,他需要知道所有的具体的同事类,用一个集合来管理它们,并接收某个同事的消息,完成相应的任务。

代码实现

#include<string>
#include<iostream>
#include<vector>
using namespace std;
class Mediator;
class Colleague{
public:
	Mediator* getMediator();
	void setMediator(Mediator* const mediator);
	Colleague(Mediator* mediator);
	virtual void Notify(string message)=0;
private:
	Mediator* m_mediator;
};

class Mediator{
public:
	virtual void send(string message,Colleague* colleague)=0;
	virtual void add(Colleague* colleague)=0;
};

Mediator* Colleague::getMediator(){
	return m_mediator;
}
void Colleague::setMediator(Mediator* mediator){
	m_mediator = mediator;
}
Colleague::Colleague(Mediator* mediator):m_mediator(mediator){

}


class ConcreteColleague1:public Colleague{
public:
	ConcreteColleague1(Mediator* mediator):Colleague(mediator){

	}
	void send(string message){
		getMediator()->send(message,this);
	}
	void Notify(string message){
		cout<<"colleague1 received :"<<message<<endl;
	}
};
class ConcreteColleague2:public Colleague{
public:
	ConcreteColleague2(Mediator* mediator):Colleague(mediator){

	}
	void send(string message){
		getMediator()->send(message,this);
	}
	void Notify(string message){
		cout<<"colleague2 received :"<<message<<endl;
	}
};
 
class ConcreteMediator:public Mediator{
public:
	void add(Colleague* colleague){
		colleagueList.push_back(colleague);
	}
	void send(string message,Colleague* colleague){
		for(auto val:colleagueList){
			val->Notify(message);
		}
	}
private:
	vector<Colleague*> colleagueList;
};


int main(){
	Mediator* m=new ConcreteMediator();
	ConcreteColleague1* colleague1=new ConcreteColleague1(m);
	ConcreteColleague2* colleague2=new ConcreteColleague2(m);
	m->add(colleague1);
	m->add(colleague2);
	colleague1->send("good morning!");
	colleague2->send("good night");
	return 0;
}

2、命令模式

介绍

命令模式将请求以命令的形式封装如一个对象中,并传递给调用对象,使得可以用不同的请求来对调用客户参数化。

请添加图片描述

角色

  • 一个客户端协议类,其中定义了不同命令的具体实现方式。
  • 一个抽象的命令类,声明了一个命令启动函数
  • 若干个具体的命令类,拥有一个协议类的指针,根据自己的类型,在各自的命令启动函数中调用协议类中相应的函数
  • 一个服务者对象,拥有一个存储命令的容器,和一个添加命令的接口,一个处理命令的接口。

代码实现

模拟一个游戏商店的功能,商店可以有加钱、加钻石、加装备等功能,于是定义一个商店里的协议,有这三种功能的具体实现。然后定义这三种命令的类,分别根据自己的类型去调用协议中规定的功能。商店(server)可以接收命令,再去一个个处理。

#include<iostream>
#include<queue>
#include<windows.h>
using namespace std;

class HandleClientProtocal{
public:
	void AddMoney(){
		cout<<"AddMoney()"<<endl;
	}
	void AddDiamond(){
		cout<<"addDiamond()"<<endl;
	}
	void AddEquipment(){
		cout<<"AddEquipment()"<<endl;
	}
};

class AbstructCommand{
public:
	virtual void handle()=0;
};


class AddMoneyCommand:public AbstructCommand{
public:
	AddMoneyCommand(HandleClientProtocal* protocal){
		this->pProtocal=protocal;
	}
	virtual void handle(){
		this->pProtocal->AddMoney();
	}
private:
	HandleClientProtocal* pProtocal;
};

class AddDiamondCommand:public AbstructCommand{
public:
	AddDiamondCommand(HandleClientProtocal* protocal){
		this->pProtocal=protocal;
	}
	virtual void handle(){
		this->pProtocal->AddDiamond();
	}
private:
	HandleClientProtocal* pProtocal;
};

class AddEquipmentCommand:public AbstructCommand{
public:
	AddEquipmentCommand(HandleClientProtocal* protocal){
		this->pProtocal=protocal;
	}
	virtual void handle(){
		this->pProtocal->AddEquipment();
	}
private:
	HandleClientProtocal* pProtocal;
};

class Server{
public:
	void addRequest(AbstructCommand* command){
		m_commands.push(command);
	}
	void startHandle(){
		while(!m_commands.empty()){
			Sleep(2000);
			AbstructCommand* command=m_commands.front();
			command->handle();
			m_commands.pop();
		}
	}
private:
	queue<AbstructCommand*> m_commands;
};

int main(){
	HandleClientProtocal* protocal=new HandleClientProtocal;
	AbstructCommand* addmoney=new AddMoneyCommand(protocal);
	AbstructCommand* adddiamond=new AddDiamondCommand(protocal);
	AbstructCommand* addequipment=new AddEquipmentCommand(protocal);

	Server* server=new Server;
	server->addRequest(addmoney);
	server->addRequest(adddiamond);
	server->addRequest(addequipment);

	server->startHandle();
	return 0;
}

3、访问者模式

简介

访问者模式封装一些对于某些数据结构各元素的操作,在不改变数据结构元素的前提下定义作用于这些元素的新操作,将操作与数据结构分离。原理是在被访问的类中添加一个对外提供接待访问者的接口。

应用于当需要对某些数据结构元素进行一些操作,同时避免这些操作污染这些元素的场景。

请添加图片描述

角色

  • 一个抽象的行动类,提供对数据结构中元素的非污染的操作。
  • 若干个具体的行动类
  • 一个抽象的封装被访问数据结构元素的类,提供一个参数为抽象行动类指针的接口
  • 若干个具体的封装被访问数据结构元素的类,实现父类中提供的接口
  • 一个封装被访问数据结构的类,提供对数据结构中元素的修改接口,提供一个参数为抽象的行动类指针的接口。

代码实现

模拟观众对一组歌手的评价(歌手有男人和女人)。先定义评价操作的抽象类,再实现具体的评价(成功或失败)。定义人的抽象类,再定义男人女人的具体类,提供接收评价的接口。定义一个歌手的集合类,提供对歌手的添加操作,和一个批量对歌手进行评价的接口,其中遍历集合中的歌手并传递此评价。

#include<iostream>
#include<list>
using namespace std;

class Man;
class Woman;

class Action{
public:
	virtual void getManResult(Man* man)=0;
	virtual void getWomanResult(Woman* woman)=0;


};

class Success:public Action{
public:
	void getManResult(Man* man) ;
	void getWomanResult(Woman* woman);
};

class Fail:public Action{
public:
	void getManResult(Man* man) ;
	void getWomanResult(Woman* woman);
};

class Person{
public:
	Person(string name):name(name){}
	virtual void accept(Action* action)=0;
	string name;
};

class Man:public Person{
public:
	Man(string name):Person(name){}
	void accept(Action* action){
		action->getManResult(this);
	}
};

class Woman:public Person{
public:
	Woman(string name):Person(name){}
	void accept(Action* action){
		action->getWomanResult(this);
	}
};

void Success:: getManResult(Man* man) {
	cout<<"A man "<<man->name<<" said success!"<<endl;
}
void Success::getWomanResult(Woman* woman){
	cout<<"A woman "<<woman->name<<" said success"<<endl;
}
void Fail::getManResult(Man* man) {
	cout<<"A man "<<man->name<<" said fail"<<endl;
}
void Fail::getWomanResult(Woman* woman){
	cout<<"A woman"<<woman->name<<" said fail"<<endl;
}
class Singer{
public:
	void attach(Person* p){
		persons.push_back(p);
	}
	void detach(Person* p){
		persons.remove(p);
		delete p;
	}

	void display(Action* action){
		for(auto val:persons){
			val->accept(action);
		}
	}
private:
	list<Person*> persons;
};

int main(){
	Singer* obj=new Singer;
	obj->attach(new Man("jack"));
	obj->attach(new Woman("ammy"));
	Success* success=new Success;
	obj->display(success);
	Fail* fail=new Fail;
	obj->display(fail);
	return 0;
}


  • 后记:2023农历新年快乐,学习不能停止,变得更强。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值