1. 概述
为其它对象提供一种代理以控制对这个对象的访问解决的问题:如果直接访问对象比较困难,或直接访问会给使用者或系统带来一系列问题。这样对于客户端(调用者)来说,就不需要直接与真实对象进行交互,解除了调用者与真实对象的耦合。
2.代理模式的好处
代理模式的一个好处就是对外部提供统一的接口方法,而代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展。也就是说,我要修改真实角色的操作的时候,尽量不要修改他,而是在外部在“包”一层进行附加行为,即代理类。例如:接口A有一个接口方法operator(),真实角色:RealA实现接口A,则必须实现接口方法operator()。客户端Client调用接口A的接方法operator()。现在新需求来了,需要修改RealA中的operator()的操作行为。怎么办呢?如果修改RealA就会影响原有系统的稳定性,还要重新测试。这是就需要代理类实现附加行为操作。创建代理ProxyA实现接口A,并将真实对象RealA注入进来。ProxyA实现接口方法operator(),另外还可以增加附加行为,然后调用真实对象的operator()。从而达到了“对修改关闭,对扩展开放”,保证了系统的稳定性。我们看客户端Client调用仍是接口A的接口方法operator(),只不过实例变为了ProxyA类了而已。也就是说代理模式实现了ocp原则。
3.涉及到的角色
Subject:抽象主题类,声明真实主题与代理的共同接口方法。
RealSubject:真实主题类,定义了代理所表示的真实对象,客户端通过代理类间接的调用真实主题类的方法。
ProxySubject:代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
4.适用性
远程代理:为一个位于不同地址空间的的对象提供一个本地的代理。(.NET的WCF的远程代理)
虚拟代理:如果需要创建一个消耗较大的对象,先创建一个消耗较小的对象来表示,真实对象只在需要时才被真实创建。(HTML图片 加载)
安全代理:用来控制对真实对象的访问权限
智能指引:当调用真实对象时,代理提供一些额外的操作。如将对象被操作的次数记录起来等。
缓冲代理:为某一个目标操作提供临时的存储空间,以便更多客户端共享此结果。
防火墙代理:保护目标不让恶意用户接近。
同步化代理:使几个用户能同时使用一个对象而没有冲突。
5.结构:
6.简单代理了模式实例:
抽象主题类:
package com.proxy;
/**
* @author lxp
*
* @TODO
*
*/
//抽象主题类
public interface Computer {
//卖电脑
public abstract void sellComputer();
}
具体主题类:
package com.proxy;
/**
* @author lxp
*
* @TODO
*
*/
// 定义电脑厂家(真正实现卖电脑的实体)
public class ComputerProduce implements Computer {
// 顾客
String Customer_name;
public ComputerProduce(String Customer_name) {
this.Customer_name = Customer_name;
}
@Override
public void sellComputer() {
// TODO Auto-generated method stub
System.out.println("厂家将电脑销售给了" + Customer_name);
}
}
代理主题类:
package com.proxy;
/**
* @author lxp
*
* @TODO
*
*/
public class ComputerProxy implements Computer {
// 创建厂家对象
ComputerProduce computerProduce;
public ComputerProxy(String Customer_name) {
// TODO Auto-generated constructor stub
computerProduce = new ComputerProduce(Customer_name);
}
@Override
public void sellComputer() {
// TODO Auto-generated method stub
computerProduce.sellComputer();//代理实现抽象主题类方法,实际调用具体主题类的实现方法
}
}
测试类:
package com.proxy;
/**
* @author lxp
*
* @TODO
*
*/
public class ProxyDemo {
public static void main(String[] args) {
// 创建电脑代理对象
ComputerProxy computerProxy = new ComputerProxy("nocol");
// 代理销售电脑
computerProxy.sellComputer();
}
}
实验结果: