C++设计模式-- 2.代理模式 和 外观模式

本文详细介绍了代理模式,包括定义、角色和职责,以及代码演示。同时探讨了外观模式,如迪米特法则的应用和子系统角色、外观角色的区分。文章还给出了适用场景,涉及复杂系统简化接口和降低耦合度等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合 或不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式有以下三种角色:
Subject(抽象主题角色):真实主题与代理主题的共同接口。
RealSubject(真实主题角色):定义了代理角色所代表的真实对象。
Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。

代码演示:

//抽象主题角色
//抽象的公共接口
class AbstractCommonInterface
{
public:
	virtual void run() = 0;
	virtual ~AbstractCommonInterface() {};
};
//真实主题角色
//真实的系统
class MySystem :public AbstractCommonInterface
{
public:
	void run() override
	{
		cout << "系统启动....." << endl;
	}
};
在这里插入代码片
//代理主题角色
//必须要有权限验证,不是所有人都能来启动我的系统,提供用户名和密码
class MySystemProxy :public AbstractCommonInterface
{
public:
	MySystemProxy(string mUserName, string mPassword) : mySystem(new MySystem){
		this->mUserName = mUserName;
		this->mPassword = mPassword;
	};

	~MySystemProxy(){ 
		if (mySystem != nullptr) {
			delete mySystem;
		}	
	};
	
	bool checkUserNameAndPassword() {
		if (mUserName == "admin" && mPassword == "123")
		{
			return true;
		}
		else {
			return false;
		}
	}

	void run() override
	{
		if (checkUserNameAndPassword())
		{
			this->mySystem->run();//调真实的服务系统
		}else {
			cout << "accout or password is error!" << endl;
		}
	}
private:
	MySystem* mySystem;//真实系统的指针
	string mUserName; //账号
	string mPassword; //密码
};

测试调用:

int main(int argc, char* argv[])
{
	AbstractCommonInterface* mySystemProxy = new MySystemProxy("admin","123");
	mySystemProxy->run();
	delete mySystemProxy;
	return 0;
}

输出结果:
在这里插入图片描述
代理模式类的UML图如下:
在这里插入图片描述

外观模式

根据迪米特法则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。
Facade模式也叫外观模式,是由GoF提供的23种设计模式中的一种。
Facade模式为一组有类似功能的类群,比如类库,子系统等待,提供一个一致的简单界面。这个一致的简单界面被称作Facade。
外观模式就是将复杂的子类系统抽象到同一个接口进行管理,外界只需要通过此接口与子类系统进行交互,而不必要直接与复杂的子类系统进行交互

角色和职责

Facade(外观角色):为调用方,定义简单的调用接口。
SubSystem(子系统角色):功能提供者。指提供功能的类群(模块或子系统)。

代码演示一:

子系统代码

//子系统 1
class SubSystem1
{
public:
	void run() {
		cout << "子系统一运行..." << endl;
	}
};

//子系统 2
class SubSystem2
{
public:
	void run() {
		cout << "子系统二运行..." << endl;
	}
};

//子系统 3
class SubSystem3
{
public:
	void run() {
		cout << "子系统三运行..." << endl;
	}
};

//子系统 4
class SubSystem4
{
public:
	void run() {
		cout << "子系统四运行..." << endl;
	}
};

外观类代码

class Facade
{
public:
	Facade() {
		pSystem1 = new SubSystem1;
		pSystem2 = new SubSystem2;
		pSystem3 = new SubSystem3;
		pSystem4 = new SubSystem4;
	}

	~Facade() {
		delete pSystem1;
		delete pSystem2;
		delete pSystem3;
		delete pSystem4;
	}

	void runSystem(){
		pSystem1->run();
		pSystem2->run();
		pSystem3->run();
		pSystem4->run();
	}

private:
	SubSystem1* pSystem1;
	SubSystem2* pSystem2;
	SubSystem3* pSystem3;
	SubSystem4* pSystem4;
};

注意:因为Facade类的成员变量SubSystem1/2/3/4类型的指针,而不是SubSystem1类型的实例是其成员变量,
所以这里Facade类和SubSystem1/2/3/4都不能称为关联。又因为Facade类的构造函数中,用到了SubSystem1/2/3/4类。
所以Facade类依赖于SubSystem1/2/3/4类。Facade类和SubSystem1/2/3/4类是依赖关系。
拓展:关联是“HAS”关系,依赖是“USE”关系 。A类关联B类,指的是B类对象作为A类的属性存在,称为“has”关系。
A类依赖B类,指的是B的对象作为A类的方法参数或者在A类的方法内 存在,称为“use”关系 。
测试调用代码

void test(){
	
	Facade* facade = new Facade;
	facade->runSystem();
}

int main(int argc, char *argv[])
{
	test()
	
	return 0;
}

针对上例的外观模式UML类图:
在这里插入图片描述

代码演示二:

根据类图,实现家庭影院外观模式
实现KTV模式:
开启时:电视打开,灯关掉,音响打开,麦克风打开,dvd打开。
关闭时:电视关掉,灯打开,音响关掉,麦克风关掉,dvd关掉。
实现游戏模式:
开启时:电视打开,音响打开,游戏机打开。
关闭时:电视关掉,音响关掉,游戏机关掉。

子系统角色:

//电视机
class Television
{
public:
	void On(){
		cout << "电视机打开...." << endl;
	}

	void Off(){
		cout << "电视机关闭...." << endl;
	}
};

//灯
class Light
{
public:
	void On(){
		cout << "灯打开...." << endl;
	}

	void Off(){
		cout << "灯关闭...." << endl;
	}
};

//音箱
class Audio
{
public:
	void On(){
		cout << "音箱打开...." << endl;
	}

	void Off(){
		cout << "音箱关闭...." << endl;
	}
};

//麦克风
class Microphone
{
public:
	void On(){
		cout << "麦克风打开...." << endl;
	}

	void Off(){
		cout << "麦克风关闭...." << endl;
	}
};

//DVD播放器
class DVDPlayer
{
public:
	void On(){
		cout << "DVD播放器打开...." << endl;
	}

	void Off(){
		cout << "DVD播放器关闭...." << endl;
	}
};

//游戏机
class Gamemachine
{
public:
	void On(){
		cout << "游戏机打开...." << endl;
	}

	void Off(){
		cout << "游戏机关闭...." << endl;
	}
};

外观角色:

//KTV模式
class KTVMode
{
public:
	KTVMode(){
		pTv = new Television;	
		pLight = new Light;	
		pAudio = new Audio;	
		pMicrophone = new Microphone;	
		pDvd = new DVDPlayer;	
	}
	
	~KTVMode(){
		delete pTv;	
		delete pLight;	
		delete pAudio;	
		delete pMicrophone;	
		delete pDvd;	
	}
	
	void OnKTV(){
		pTv->On();
		pLight->Off();
		pAudio->On();
		pMicrophone->On();
		pDvd->On();
	}

	void OffKTV(){
		pTv->Off();
		pLight->On();
		pAudio->Off();
		pMicrophone->Off();
		pDvd->Off();
	}

private:
	Television* pTv;
	Light* pLight;
	Audio* pAudio;
	Microphone* pMicrophone;
	DVDPlayer* pDvd;
};


//游戏模式
class GameMode
{
public:
	GameMode(){
		pTv = new Television;	
		pAudio = new Audio;	
		pGamemachine = new Gamemachine;	
	}
	
	~GameMode(){
		delete pTv;	
		delete pAudio;	
		delete pGamemachine;		
	}
	
	void OnGame(){
		pTv->On();
		pAudio->On();
		pGamemachine->On();
	}

	void OffGame(){
		pTv->Off();
		pAudio->Off();
		pGamemachine->Off();
	}

private:
	Television* pTv;
	Audio* pAudio;
	Gamemachine* pGamemachine;
};

测试调用:

//测试KTV模式
void testKTVMode()
{
	KTVMode* pKTVMode = new KTVMode;
	pKTVMode->OnKTV();//开启KTV模式
	//pKTVMode->OffKTV();//关闭KTV模式
}

//测试游戏模式
void testGameMode()
{
	GameMode* pGameMode = new GameMode;
	pGameMode->OnGame();//开启游戏模式
	//pGameMode->OffGame();//关闭游戏模式
}


int main(int argc, char *argv[])
{
	testKTVMode();
	//testGameMode();
	return 0;
}

针对上例的外观模式UML类图:
在这里插入图片描述

外观模式适用场景

1.复杂系统需要简单入口使用。
2.客户端程序与多个子系统之间存在很大的依赖性。
3.在层次化结构中,可以使用外观模式定义系统中每一层的入口,
层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值