一、概念
代理模式,为其他对象提供一种代理以控制对这个对象的访问。
二、使用场景
1、远程代理:对一个位于不同地址空间的对象提供一个本地代表,隐藏这个对象存在于不同地址空间的事实,例如RMI的stub(RMI也是比较重要的概念)。这个不同的地址空间可以是在同一主机中,也可以是在不同主机中。
2、虚拟代理:如果创建一个开销比较大的对象,可以先创建开销小的代理对象,真实对象只在需要时才被真正创建,延迟加载。
3、安全代理(保护代理):用来控制真实对象访问时的权限。
4、智能引用代理:当调用真实对象时,代理提供一下额外的操作,例如把对象被调用的次数记录下来(即引用计数)
5、缓冲代理:为某一目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
三、角色分析
抽象角色(Subject):声明真实对象和代理对象的共用接口,这样使得在任何使用真实对象(RealSubject)的地方都可以使用代理对象(Proxy)。
代理角色(Proxy):代理对象角色内部包含对真实对象的引用,从而可以操作真实对象,同时代理对象提供域真实对象相同的接口以便任何时刻都能代替真实对象。代理对象可以实现上面使用场景所述的功能。
真实角色(RealSubject):代理模式所代表的真实对象。
四、代码示例
抽象接口(Subject.java):
package com.mingmingcome.designpattern.proxy.staticproxy;
/**
* @ClassName: Subject
* @Description: 抽象接口:代理对象和真实对象的共用接口
* @author: luhaoming
* @date: 2018年8月12日 下午2:56:43
*/
public interface Subject {
void request();
}
代理类(Proxy.java):
package com.mingmingcome.designpattern.proxy.staticproxy;
/**
* @ClassName: Proxy
* @Description: 代理对象:代理对象角色内部包含对真实对象的引用,从而可以操作真实对象,
* 同时代理对象提供域真实对象相同的接口以便任何时刻都能代替真实对象。
* @author: luhaoming
* @date: 2018年8月12日 下午3:00:10
*/
public class Proxy implements Subject {
// 真实主题对象的引用
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
preRequest();
// 执行真实对象的方法
subject.request();
afterRequest();
}
private void preRequest() {
System.out.println("这是在调用真实对象之前做的事情。。。");
}
private void afterRequest() {
System.out.println("这是在调用真实对象之后做的事情。。。");
}
}
真实主题类(RealSubject):
package com.mingmingcome.designpattern.proxy.staticproxy;
/**
* @ClassName: RealSubject
* @Description: 真实对象
* @author: luhaoming
* @date: 2018年8月12日 下午3:10:59
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实的请求");
}
}
测试类(TestStaticProxy.java):
package com.mingmingcome.designpattern.proxy.staticproxy;
/**
* @ClassName: TestStaticProxy
* @Description: 静态代理测试类
* @author: luhaoming
* @date: 2018年8月12日 下午3:22:19
*/
public class TestStaticProxy {
public static void main(String[] args) {
Subject subject = new RealSubject();
Proxy proxy = new Proxy(subject);
proxy.request();
}
}
执行结果:
这是在调用真实对象之前做的事情。。。
真实的请求
这是在调用真实对象之后做的事情。。。
五、优缺点
1、可以做到在不修改真实对象的功能下,对目标功能扩展
2、缺点:因为代理对象要与真实对象实现同一个接口,这样就会有很多与真实对象类相对应的代理类。另外,如果接口增删方法,都要同时维护真实对象类和代理对象类。
3、在编译期就决定了代理类的功能,决定为哪个真实对象代理,以后不可修改