【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

運行一下:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章