【设计模式学习笔记十三】【结构型模式】【代理模式(Proxy)】

本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:http://blog.csdn.net/lovelion/article/details/17517213

主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。

我应该理解和掌握的:

1)能够画出这个设计模式的架构框图;

2)能够根据架构框图写出对应的伪代码;

3)这个模式的应用场景,主要优缺点。

1.代理模式

在软件开发中,有一种模式类似于代购,即客户端由于某种原因不想或不能直接访问一个对象,此时可以通过一个代理对象来实现间接访问,该方案被称为代理模式。

(1)定义

代理模式:为其他对象提供一种代理以控制对这个对象的访问。

代理又可分为四种:

a)远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是同一台主机中,也可以在另一台主机中,远程代理又称为大使。

b)虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正的创建。

c)保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。

d)缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

e)智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来,比如智能指针。

1)代理模式结构图


2)参与者

a) Subject(抽象主题角色):定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用proxy。

b) RealSubject(真实主题角色):定义了Proxy所代表的实体。

c) Proxy(代理):保存一个引用是的代理可以访问实体;提供一个与Subject相同的接口,这样代理就可以用来替代实体;控制对实体的存取,并可能负责创建或删除它;其他功能依赖于代理的类型。

3)看图写代码

/*
** FileName     : ProxyPattern
** Author       : lin005
** Date         : 2015/01/29
** Description  : More information, please go to http://blog.csdn.net/amd123456789
*/
#include<iostream>
#include<windows.h>
using namespace std;
//抽象主题角色
class Subject
{
public:
	virtual void Request() = 0;
};
//真实主题角色
class RealSubject:public Subject
{
public:
	void Request()
	{
		cout<<"RealSubject Request()"<<endl;
	}
};
//代理
class Proxy:public Subject
{
public:
	Proxy()
	{
		real = new RealSubject();
	}
	~Proxy()
	{
		if(real != NULL)
		{
			delete real;
			real = NULL;
		}
	}
	void preRequest()
	{
		cout<<"preRequest()"<<endl;
	}
	void postRequest()
	{
		cout<<"postRequest"<<endl;
	}
	//调用真正实体
	void Request()
	{
		preRequest();
		real->Request();
		postRequest();
	}
private:
	RealSubject *real;
};
//客户端测试类
int main()
{
	
	Subject *proxy = new Proxy();
	proxy->Request();

	if(proxy)
	{
		delete proxy;
		proxy = NULL;
	}
	return 0;
}
4)智能指针

智能指针,使用引用计数时,也可以看做是代理模式的应用。下面例子中,SmartPtr就是代理类,实际对象是ptr;SmartPtr代理ptr的行为,运用引用计数,实现智能指针。

代码来自百度百科:

/*
** FileName     : ProxyPattern
** Author       : lin005
** Date         : 2015/01/30
** Description  : More information, please go to http://blog.csdn.net/amd123456789
*/
//被代理的对象
class Stub
{
public:
	void print()
	{
		cout<<"test"<<endl;
	}
	~Stub()
	{
		cout<<"stub::destructor"<<endl;
	}
};
//可以看做代理
template<typename T>
class SmartPtr
{
public:
	SmartPtr(T* p = 0):ptr(p),count(new size_t(1)){}
	SmartPtr(const SmartPtr<T> & src):ptr(src.ptr),count(src.count)
	{
		++*count;
	}
	//重载赋值操作符
	SmartPtr& operator=(const SmartPtr & src)
	{
		++*src.count;
		release();
		ptr = src.ptr;
		count = src.count;
		return *this;
	}
	T* operator->()
	{
		if(ptr)
			return ptr;
	}
	const T* operator->()const
	{
		if(ptr)
			return ptr;
	}
	T& operator*()
	{
		if(ptr)
			return *ptr;
	}
	const T& operator*()const
	{
		if(ptr)
			return *ptr;
	}
	~SmartPtr()
	{
		release();
	}
private:
	void release()
	{
		if(--*count == 0)
		{
			delete ptr;
			delete count;
		}
	}
private:
	T* ptr;//真实对象
	size_t* count;//引用计数
};
int main()
{
	//智能指针,类型为Stub
	SmartPtr<Stub> t;
	t->print();//print test

	SmartPtr<Stub> t1(new Stub());
	SmartPtr<Stub> t2(t1);
	SmartPtr<Stub> t3(new Stub());
	t3= t2;//call t3 destructor
	t1->print(); //print
	(*t3).print(); //print
	return 0;
	/*
	输出结果:
	test
	stub::destructor (析构t3)
	test
	test
	stub::destructor (析构t1)
	请按任意键继续. . .
	*/
}

(2)总结

1)优点

a) 能够协调调用者和被调用者,在一定程度上降低了系统的耦合。

b) 客户端可以针对抽象角色进行编程。

2)缺点

a) 增加代理对象有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。

b) 是在代理模式需要额外的工作,并且有些代理模式实现过程较为复杂,例如远程代理。

(3)适用场景

1)远程代理为一个对象在不同的地址空间提供局部代表;

2)虚代理根据需要创建开销很大的对象。

3)当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时使用保护代理

4)当需要为一个对象的访问提供额外的操作时,可以使用智能引用代理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值