在做面向對象的軟件開發時我們往往想達到更高的代碼可複用性和更合理的軟件顆粒度。
根據《設計模式——可複用面向對象軟件的基礎》所說:“你必須找到相關的對象,以適當的顆粒度將他們迴歸類,再定義類的接口和繼承層次,建立對象之間的基本關係。你的設計應該對手頭的問題有針對性,同時對將來的問題和需求也要有足夠的通用性。”
內行的設計者知道:不是解決任何問題都要從頭做起。他們更願意複用以前使用的解決方案。這些重複的模式方案解決特定的問題,使得面向對象的設計更靈活、優雅,最終複用性更好。它們幫助設計者將新的設計建立在以往的工作基礎上,複用以往的成功設計方案。一個熟悉這些設計模式的設計者不需要再去發現它們,而能夠立即將他們應用於設計問題中。
本系列文章主要參考文獻爲——設計模式,可複用面向對象軟件的基礎(Design Patterns Elements of Reusable Object-Oriented SoftWare Erich.),內部代碼基本用C++語言編寫。
彙總鏈接:23種設計模式C++實現——概要(索引彙總)
摘要
本章主要說明代理模式,該設計模式主要意圖是:在需要時才創建和初始化,不需要同時創建這些對象。
代理模式有以下四種常見情況:
- 遠程代理
- 虛代理
- 保護代理
- 智能引用
具體實現下邊我們就通過以下的栗子來說明什麼是代理模式。
主要參與者
該設計模式的參與者有4個,分別是:
- Subject(PhotoInfo) 接口基類
- Proxy(BigPhotoProxy) 通過該對象來實現對被代理對象的訪問或控制
- RealSubject(BigPhoto)定義Proxy所代表的實體對象
- Client 用戶
優點
——虛代理
- 根據需求來控制是否創建實例對象
- 在實例對象與外部使用接口之間加一層緩衝,增加安全性
具體實現代碼
代理模式中的虛代理以大圖片加載爲例,當我們在訪問網站時是否常遇到有些圖片未加載時顯示一個小圖標或壓縮圖片來替代原來位置,當點擊下查看原圖或稍等一會就會加載出原始高清圖片,未加載時的小圖片其實就可以通過代理模式實現,原圖則是被代理的實例對象,通過點擊或一定時間處理來創建或加載。
接口基類(Subject)
#ifndef PHOTOINFO_H
#define PHOTOINFO_H
/****************************************************************
Doc : photoinfo.h
Author : BingLee
Date : 2019-12-23
Info : Proxy Design Patten
https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#include <string>
using namespace std;
//This is a class include photo base model information
class PhotoInfo
{
public:
PhotoInfo(){}
// virtual ~PhotoInfo(){}
virtual void GetRealPhoto(){}
protected:
string m_Photo;
};
被代理的實體對象(RealSubject)
//This is a real big photo with "m_Photo"
class BigPhoto : public PhotoInfo
{
public:
BigPhoto(string photo){m_Photo = photo;}
~BigPhoto(){}
void GetRealPhoto()
{
printf("Get real ");
printf(m_Photo.c_str());
printf(" for view ! \n");
}
};
代理(Proxy)
//This is BigPhoto proxy
class BigPhotoProxy : public PhotoInfo
{
public:
BigPhotoProxy(string photo):m_pBigPhoto(NULL){
//Befor askreal photo for view, see GetRealPhoto get some base info
m_Photo = photo;
printf("This is a proxy of %s.\n",m_Photo.c_str());
}
~BigPhotoProxy(){}
void GetRealPhoto()
{
//ask real photo to view
if(m_pBigPhoto == NULL)
{
m_pBigPhoto = new BigPhoto(m_Photo);
}
m_pBigPhoto->GetRealPhoto();
}
private:
BigPhoto *m_pBigPhoto;
};
#endif // PHOTOINFO_H
用戶(Client)
/****************************************************************
Doc : main.cpp
Author : BingLee
Date : 2019-12-23
Info : Proxy Design Patten
https://blog.csdn.net/Bing_Lee (C)All rights reserved.
******************************************************************/
#include <QCoreApplication>
#include "photoinfo.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BigPhotoProxy *pBigPhotoProxy = new BigPhotoProxy("Planet Photo");
pBigPhotoProxy->GetRealPhoto();
return a.exec();
}
輸出結果:
補充說明
該模式當前只寫了一個虛代理的實現,虛代理可進行最優化控制,根據需求來創建或加載實例對象。
本篇博客中的代碼均已通過編譯,如有Bug,請提出寶貴意見~
注:文章內函數可以把除Client對象放在一個頭文件中,Client文件放在主函數中執行。