代理(Proxy),首先映入大脑中的肯定是网络上为数众多的代理服务器。我们的客户机由于各种原因,不能直接连接到真正的服务器、直接访问速度慢,有的应用中甚至在代理服务器上作权限的访问控制。大部分代理服务器都有一个缓存功能,当客户机访问某内容的时候,代理服务器首先查找本地缓存里是否有这个内容,如果有则直接将其返回,否则代理服务器将向真正的服务器发送请求,将真正的服务器的响应内容发送给客户端而且将这个内容也在本地缓存中保留一份,以备后用。
其实今天我们要谈的代理模式也是和这个类似。
定义
为其他对象提供一种代理以控制对这个对象的访问。
适用性
有四种常用的情况:(1)远程代理,(2)虚代理,(3)保护代理,(4)智能引用。本文主要介绍虚代理和智能引用两种情况。
实例
main(),西门庆
IKindWomen,接口
CWangPo,代理
CPanJinLian,实际执行者之一
CJiaShi,实际执行者之二
说明:代理和实际执行者派生于共同的接口,代理拥有实际执行者的实例。代理的每一个函数(接口的实现函数),直接调用实际执行者的对应接口函数。
注意:代理只是简单的装载,然后调用实际执行者的函数。
看代码:
//IKindWomen.h
#pragma once
class IKindWomen
{
public:
IKindWomen(void);
virtual ~IKindWomen(void);
virtual void MakeEyesWithMan() = 0;
virtual void HappyWithMan() = 0;
};
//WangPo.h
#pragma once
#include "ikindwomen.h"
class CWangPo :
public IKindWomen
{
public:
CWangPo(IKindWomen *pKindWomen);
~CWangPo(void);
void HappyWithMan(void);
void MakeEyesWithMan(void);
private:
IKindWomen *m_pKindWomen;
};
//WangPo.cpp
#include "StdAfx.h"
#include "WangPo.h"
CWangPo::CWangPo(IKindWomen *pKindWomen)
{
this->m_pKindWomen = pKindWomen;
}
CWangPo::~CWangPo(void)
{
delete this->m_pKindWomen;
}
void CWangPo::HappyWithMan()
{
this->m_pKindWomen->HappyWithMan();
}
void CWangPo::MakeEyesWithMan(void)
{
this->m_pKindWomen->MakeEyesWithMan();
}
//PanJinLian.h
#pragma once
#include "ikindwomen.h"
class CPanJinLian :
public IKindWomen
{
public:
CPanJinLian(void);
~CPanJinLian(void);
void HappyWithMan(void);
void MakeEyesWithMan(void);
};
//PanJinLian.cpp
#include "StdAfx.h"
#include "PanJinLian.h"
#include <iostream>
using std::cout;
using std::endl;
CPanJinLian::CPanJinLian(void)
{
}
CPanJinLian::~CPanJinLian(void)
{
}
void CPanJinLian::HappyWithMan(void)
{
cout << " 潘金莲和男人做那个... ... " << endl;
}
void CPanJinLian::MakeEyesWithMan(void)
{
cout << " 潘金莲抛媚眼 " << endl;
}
//JiaShi.h
#pragma once
#include "ikindwomen.h"
class CJiaShi :
public IKindWomen
{
public:
CJiaShi(void);
~CJiaShi(void);
void HappyWithMan(void);
void MakeEyesWithMan(void);
};
//JiaShi.cpp
#include "StdAfx.h"
#include "JiaShi.h"
#include <iostream>
using std::cout;
using std::endl;
CJiaShi::CJiaShi(void)
{
}
CJiaShi::~CJiaShi(void)
{
}
void CJiaShi::HappyWithMan(void)
{
cout << " 贾氏和男人做那个... ... " << endl;
}
void CJiaShi::MakeEyesWithMan(void)
{
cout << " 贾氏抛媚眼 " << endl;
}
//Proxy.cpp
#include "stdafx.h"
#include "WangPo.h"
#include "PanJinLian.h"
#include "JiaShi.h"
#include <iostream>
using std::cout;
using std::endl;
void DoPanJinLian()
{
CWangPo *pWangPo;
// 西门庆想找潘金莲,让王婆来安排。
pWangPo = new CWangPo(new CPanJinLian());
pWangPo->MakeEyesWithMan();
pWangPo->HappyWithMan();
delete pWangPo;
}
void DoJiaShi()
{
CWangPo *pWangPo;
// 西门庆想找贾氏,让王婆来安排。
pWangPo = new CWangPo(new CJiaShi());
pWangPo->MakeEyesWithMan();
pWangPo->HappyWithMan();
delete pWangPo;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 西门庆想找潘金莲
DoPanJinLian();
// 西门庆想找贾氏
DoJiaShi();
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
_CrtDumpMemoryLeaks();
system("pause");
return 0;
}
总结
看起来代理模式的结构和策略模式类似,都是由一个类来装载接口的一个实例,策略模式是CContext来装载,代理模式是CWangPo来装载。CContext不是从IStrategy派生,所以不需要实现IStrategy接口函数,而CWangPo是从IKindWomen派生的所以CWangPo很清楚CPanJinLian和CJiaShi的接口函数。这就是代理,代理人知道被代理人能干的事情即函数,所以代理人可以成为中介。
代理模式可以很好的将前后端分开,实现了松散耦合。代理模式属于结构型模式。上图仍然是例子中用到的类相关图,并不是代理模式的抽象类图。这样的类图更容易理解代理模式。抽象类图当然具有更高的抽象层次,但不利于理解。