在做面向对象的软件开发时我们往往想达到更高的代码可复用性和更合理的软件颗粒度。
根据《设计模式——可复用面向对象软件的基础》所说:“你必须找到相关的对象,以适当的颗粒度将他们回归类,再定义类的接口和继承层次,建立对象之间的基本关系。你的设计应该对手头的问题有针对性,同时对将来的问题和需求也要有足够的通用性。”
内行的设计者知道:不是解决任何问题都要从头做起。他们更愿意复用以前使用的解决方案。这些重复的模式方案解决特定的问题,使得面向对象的设计更灵活、优雅,最终复用性更好。它们帮助设计者将新的设计建立在以往的工作基础上,复用以往的成功设计方案。一个熟悉这些设计模式的设计者不需要再去发现它们,而能够立即将他们应用于设计问题中。
本系列文章主要参考文献为——设计模式,可复用面向对象软件的基础(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文件放在主函数中执行。