【C++设计模式】-03代理模式

代理模式

代理模式介绍

今天继续学习设计模式,今天我们来学习代理模式。其实这个模式呢在我们的生活早已经运用起来了。笔者看到这个模式就联想到了代理商。我们客户买东西一般都是经过代理商的,代理商和真正的生成产品的公司进行对接,因为代理商有钱嘛可以搞垄断赚差价嘛。其实在软件设计中的代理模式和我们现实生活中很类似。在设计模式中,我们的代理模式是这样的,客户端并不能直接访问真正的主题对象,只能通过代理对象进行间接的访问,这样我们就可通过代理对象来控制对真实主题对象的访问,可以在访问前后做一些动作,比如校验什么之类的呀。下面我们看一下标准的代理模式模型图。

代理模式标准模型图

从图中可以,为啥我们的代理对象能代理真实的主题对象 干事呢?很重要一点,他们都继承实现共同的接口。这样在需要访问真实主题对象是都可以使用代理对象 进行访问控制


代理服务器案例

在了解上面代理模式相关知识后,这个代理服务器访问的案例也就不难理解了。访问真正的服务器,需要通过代理服务器,代理服务器进行用户名密码校验,通过才允许访问真实服务器

代理服务器模型图


代理服务器代码


 
 
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <iostream>
  3. using namespace std;
  4. //抽象类,抽象的主题类
  5. class AbstractServer
  6. {
  7. public:
  8. virtual void Request() = 0;
  9. };
  10. //真正主题类,具体提供服务的类
  11. class RealServer: public AbstractServer
  12. {
  13. virtual void Request()
  14. {
  15. cout << "服务器启动..." << endl;
  16. }
  17. };
  18. //代理服务器,非真正的服务器,访问真正服务器必须通过代理服务器
  19. class ProxyServer : public AbstractServer
  20. {
  21. public:
  22. ProxyServer( string name, string pwd)
  23. {
  24. this->name = name;
  25. this->pwd = pwd;
  26. this->server = new RealServer;
  27. }
  28. // 和 真正主题类实现共同的接口,对外可以提供一致的接口!
  29. virtual void Request()
  30. {
  31. if (!CheckUser())
  32. {
  33. cout << "用户名或者密码错误..." << endl;
  34. return;
  35. }
  36. cout << "请求成功..." << endl;
  37. PreRequest();
  38. this->server->Request();
  39. PostRequest();
  40. }
  41. private:
  42. //访问服务器前 进行的动作,可以控制对真实主题类的访问
  43. bool CheckUser()
  44. {
  45. if ( "admin" == this->name && "123456" == this->pwd)
  46. {
  47. return true;
  48. }
  49. return false;
  50. }
  51. //真正访问服务器前 进行的动作,这里进行安全
  52. void PreRequest()
  53. {
  54. cout << "进入代理服务器..." << endl;
  55. }
  56. //访问服务器之后 进行的动作
  57. void PostRequest()
  58. {
  59. cout << "服务器访问完毕..." << endl;
  60. }
  61. string name;
  62. string pwd;
  63. private:
  64. AbstractServer* server;
  65. };
  66. //客户端 通过登录代理服务器 访问 真实服务器
  67. int main(int argc, char *argv[])
  68. {
  69. AbstractServer *proxy = new ProxyServer( "admin", "123456"); //登录代理服务器
  70. proxy->Request(); //通过代理服务器 访问真正服务器
  71. return EXIT_SUCCESS;
  72. }

运行结果


代理模式很容易理解,就是代替别人去做某一件事,打个比方,我们需要买水果,一般是去超市或者水果店买水果,很少有人去果园买水果,果园是生产水果的地方,但很少出售水果,在这里,水果店,超市就成了代理。

首先定义一个抽象类,提供所有的函数接口。
定义卖水果的抽象类,也就是接口,果园与超市都要继承这个类。

#pragma once
class CSellFruits//定义一个抽象类
{
public:
        CSellFruits(void);
        virtual ~CSellFruits(void);
        virtual void sellapple()=0; //定义接口,卖苹果
        virtual void sellorange()=0;//定义接口,卖橘子
};
#include "SellFruits.h"
CSellFruits::CSellFruits(void)
{
}
CSellFruits::~CSellFruits(void)
{
}

2.定义具体类,也就是果园类,果园生产水果,但是一般不买水果

#pragma once
#include "sellfruits.h"
#include <stdio.h>
class COrchard :
        public CSellFruits
{
public:
        COrchard(void);
        virtual ~COrchard(void);
        virtual void sellapple();
        virtual void sellorange();
};
#include "Orchard.h"
COrchard::COrchard(void)
{
}
COrchard::~COrchard(void)
{
}
void COrchard::sellapple()
{
        printf("Sell apple\n");
}
void COrchard::sellorange()
{
        printf("Sell orange\n");
}

3.定义代理类,代理卖水果的类

#pragma once
#include "sellfruits.h"
#include "Orchard.h"
#include <stdio.h>
class CProcySellFruits :
        public CSellFruits
{
public:
        CProcySellFruits(void);
        virtual ~CProcySellFruits(void);
        virtual void sellapple();
        virtual void sellorange();
private:
        CSellFruits *p_SellFruits; //传入接口对象
};
#include "ProcySellFruits.h"
CProcySellFruits::CProcySellFruits(void):p_SellFruits(NULL)
{
}
CProcySellFruits::~CProcySellFruits(void)
{
}
void CProcySellFruits::sellapple()
{
        if(this->p_SellFruits==NULL)
        {
                this->p_SellFruits=new COrchard(); //用被代理的类实例化
        }
        this->p_SellFruits->sellapple();//代理果园卖苹果
}
void CProcySellFruits::sellorange()
{
        if(this->p_SellFruits==NULL)
        {
                this->p_SellFruits=new COrchard(); //用被代理的类实例化
        }
        this->p_SellFruits->sellorange();//代理果园卖橘子
}

4.实际调用

CSellFruits* p=new CProxySellFruits(); //用代理类卖水果,然后强转为基类
p->SellApple();
p->SellOrange();

版权声明:最终版权归YBAidam所有 https://blog.csdn.net/Aidam_Bo/article/details/81116034

C++设计模式 - 代理模式详解一

2018-12-17 22:38:26 更多

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/wb175208/article/details/84984169

代理模式:提供一种可以对真实对象的访问对象,隐藏真实的对象,去除真实对象的非必要的职责。

大家都喜欢玩游戏,单机版游戏如红警、CS、暗黑了等(不小心就暴露了年龄),网络游戏如传奇、魔兽以及吃鸡游戏、王者荣耀等,作为一个会写程序的游戏玩家,咱们通过编程来实现玩游戏的过程。

  • 1.接口基类

首先提取出一个接口基类,这个基类中值定义了游戏的基本流程,登陆账号、打游戏、升级、退出账号等。

#pragma once
#include <string>

//游戏玩家接口

class IPlayer {
public:
	IPlayer();
	IPlayer(std::string account, std::string pwd);
	~IPlayer();

	//登录游戏
	virtual void login();
	
	//玩游戏
	virtual void play();
	
	//升级
	virtual void update();
	
	//退出登录
	virtual void logout();
protected:
	std::string _account;//账号
	std::string _password;//密码
}; 
1234567891011121314151617181920212223242526
#include "IPlayer.h"

IPlayer::IPlayer(std::string account, std::string pwd) {
	this->_account = account;
	this->_password = pwd;
}

IPlayer::IPlayer() {

}

IPlayer::~IPlayer() {
}

void IPlayer::login() {
}

void IPlayer::play() {

}

void IPlayer::update() {

}

void IPlayer::logout() {

}
12345678910111213141516171819202122232425262728

好,游戏的基本接口已经定义完成了。下面咱们定义两种基本的游戏玩家,一种是成人游戏玩家,一种是学社游戏玩家。因为现在国家对于游戏有比较严格的控制,对于小学生的游戏玩家也是有时间上的限制的。

  • 2.成人游戏玩家
#include "IPlayer.h"

IPlayer::IPlayer(std::string account, std::string pwd) {
	this->_account = account;
	this->_password = pwd;
}

IPlayer::IPlayer() {

}

IPlayer::~IPlayer() {
}

void IPlayer::login() {
}

void IPlayer::play() {

}

void IPlayer::update() {

}

void IPlayer::logout() {

}

IPlayer* IPlayer::getProxy() {
	return nullptr;
}
1234567891011121314151617181920212223242526272829303132
#include "AdultPlayer.h"
#include <stdio.h>

AdultPlayer::AdultPlayer(std::string account, std::string pwd)
:IPlayer( account, pwd) {
}

AdultPlayer::~AdultPlayer() {
}

void AdultPlayer::login() {
	printf("成人游戏玩家账号:%s   已经登录了游戏!\n", _account.c_str());
}

void AdultPlayer::play() {
	printf("成人游戏玩家账号:%s   开始打怪!\n", _account.c_str());
}

void AdultPlayer::update() {
	printf("成人游戏玩家账号:%s   把大BOSS打死了,升了一级!\n", _account.c_str());
}

void AdultPlayer::logout() {
	printf("成人游戏玩家账号:%s   退出了游戏!\n", _account.c_str());
}

1234567891011121314151617181920212223242526

以上就是定义了一个成人的游戏玩家,那么咱们定义一个成人游戏者玩游戏的场景。

int main() {
	//成人玩家
	IPlayer* player = new AdultPlayer("zhangsan", "123456");
	player->login();

	player->play();

	player->update();

	player->logout();
	
    return 0;
 }
12345678910111213

运行一下:
在这里插入图片描述

  • 3.学生玩家
class StudentPlayer :public IPlayer {
public:
	StudentPlayer(std::string account, std::string pwd);
	~StudentPlayer();

	//登录游戏
	void login()override;

	//玩游戏
	void play()override;

	//升级
	void update()override;

	//退出登录
	void logout()override;
};

123456789101112131415161718
StudentPlayer::StudentPlayer(std::string account, std::string pwd)
:IPlayer(account, pwd) {
}


StudentPlayer::~StudentPlayer() {
}

void StudentPlayer::login() {
	printf("学生游戏玩家账号:%s   已经登录了游戏!\n", _account.c_str());
}

void StudentPlayer::play() {
	printf("学生游戏玩家账号:%s   开始打怪!\n", _account.c_str());

}

void StudentPlayer::update() {
	printf("学生游戏玩家账号:%s   把大BOSS打死了,升了一级!\n", _account.c_str());
}

void StudentPlayer::logout() {
	printf("学生游戏玩家账号:%s   退出了游戏!\n", _account.c_str());
}

12345678910111213141516171819202122232425

咱们定义一个学生游戏玩家的使用场景,放假了,小明同学跟妈妈申请想玩游戏,妈妈也同意了;

int main() {
	//学生玩家
	IPlayer* player2 = new StudentPlayer("xiaoming", "123456");
	player2->login();

	player2->play();

	player2->update();

	player2->logout();

	return 0;
}

1234567891011121314

运行一下:
在这里插入图片描述
小明玩游戏玩的很高兴,但是快乐的日子总是短暂的,要开学了,小明就不能玩游戏了,但是如果长时间不玩的话,他的游戏级别就上不去,下次和同学聊天的时候,就感觉比别的同学低了几级,就不能跟其他的同学炫耀了,一想到这些小明同学就心痛不已。

后来他的同学强强告诉他可以让游戏代理来帮他打怪继续升级,小明一想太棒了,自己不用玩游戏,但是自己的游戏级别还是不停的在上升。

  • 4.游戏代理
class ProxyStudentPlayer :public IPlayer {
public:
	ProxyStudentPlayer(std::string name, std::string account, std::string pwd);
	ProxyStudentPlayer(std::string name,IPlayer* player);
	~ProxyStudentPlayer();

	//登录游戏
	void login()override;

	//玩游戏
	void play()override;

	//升级
	void update()override;

	//退出登录
	void logout()override;

	

private:
	std::string _proxyName;
	IPlayer* _studentPlayer;
};

12345678910111213141516171819202122232425
ProxyStudentPlayer::ProxyStudentPlayer(std::string name, std::string account, std::string pwd)
:IPlayer(account, pwd) {
	_proxyName = name;
	_studentPlayer = new StudentPlayer(account, pwd);
}

ProxyStudentPlayer::ProxyStudentPlayer(std::string name, IPlayer* player) {
	_proxyName = name;
	_studentPlayer = player;
}

ProxyStudentPlayer::~ProxyStudentPlayer() {
		
}

void ProxyStudentPlayer::login() {
	printf("游戏代理:%s  使用", _proxyName.c_str());
	_studentPlayer->login();
}

void ProxyStudentPlayer::play() {
	printf("游戏代理:%s  使用", _proxyName.c_str());
	_studentPlayer->play();
}

void ProxyStudentPlayer::update() {
	printf("游戏代理:%s  使用", _proxyName.c_str());
	_studentPlayer->update();
}

void ProxyStudentPlayer::logout() {
	printf("游戏代理:%s  使用", _proxyName.c_str());
	_studentPlayer->logout();
}

1234567891011121314151617181920212223242526272829303132333435

上学期间每次要打游戏的时候,小明都会让游戏代理大强帮自己打游戏,他只要把游戏账号登陆上就可以了。

int main() {
	//学生玩家
	IPlayer* player2 = new StudentPlayer("xiaoming", "123456");
	//代理玩家1
	ProxyStudentPlayer* proxyStudent = new ProxyStudentPlayer("大强", player2);
	proxyStudent->login();

	proxyStudent->play();

	proxyStudent->update();

	proxyStudent->logout();


	return 0;
}

1234567891011121314151617

运行一下:
在这里插入图片描述

但是他的同学强强嫌每次都要自己登陆很麻烦,就直接把自己的游戏账号和密码告诉游戏代练大强,让大强用自己的账号密码来登录玩游戏升级。

	ProxyStudentPlayer* proxyStudent2 = new ProxyStudentPlayer("大强", "qiangqiang", "123456");
	proxyStudent2->login();

	proxyStudent2->play();

	proxyStudent2->update();

	proxyStudent2->logout();

123456789

运行一下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值