代理模式
Proxy模式又叫做代理模式,是构造型的设计模式质之一,它可以为其他对象提供一种代理以控制对这个对象的访问,所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中,进行某些特别的处理
例如:买书的过程可以被称为代理模式,书一般都是由专门的出版社(被代理对象),但是我们买书的时候一般都不会去出版社那里直接购买,而是去通过书店(代理对象),例如在当当书店、新华书店里购买
一、结构与模式
- subject抽象主题角色:真实主题与代理主题的共同接口
- realsubject真实主题角色:定义了代码角色所代表的真实对象
- proxy代理主题角色:含有对真实主题角色的引用,代理角色通常在客户端调用传递给真实主题角色之前或者之后执行某些操作,而不是单纯返回真实的对象
二、普通代理示例代码
2.1 Subject
public interface Subject {
public void sailBooks();
}
2.2 RealSubject
public class RealSubject implements Subject {
@Override
public void sailBooks() {
System.out.println("出版社卖书");
}
}
2.3 ProxySubject(利用set方法与真实主题角色联系)
public class ProxySubject implements Subject {
private RealSubject realSubject;
public void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
//属于自己的操作
private void discount(){
System.out.println("打折");
}
private void coupon(){
System.out.println("赠与代金券");
}
@Override
public void sailBooks() {
//调用真实对象之前执行自己添加的操作
this.discount();
//调用真实的对象
this.realSubject.sailBooks();
this.coupon();
}
}
2.4 MainClass
public class MainClass {
public static void main(String[] args){
//直接在出版社买家
RealSubject realSubject = new RealSubject();
realSubject.sailBooks();
//通过代理模式买书
ProxySubject proxySubject = new ProxySubject();
proxySubject.setRealSubject(realSubject);
proxySubject.sailBooks();
}
}
2.5 ProxySubject(改进,通过判断与真实主题角色联系)
public class ProxySubject implements Subject {
private RealSubject realSubject;
//属于自己的操作
private void discount(){
System.out.println("打折");
}
private void coupon(){
System.out.println("赠与代金券");
}
@Override
public void sailBooks() {
//调用真实对象之前执行自己添加的操作
this.discount();
if(realSubject == null) {
synchronized (this) {
if (realSubject == null) {
realSubject = new RealSubject();
}
}
}
//调用真实的对象
this.realSubject.sailBooks();
this.coupon();
}
}
三、动态代理
从前面我们可以看到,我们需要手动的实现代理对象,例如realSubject = new RealSubject(),如果我们使用动态代理则不需要使用这个动态代理对象,通过JDK对代理的支持进行操作。
InvocationHandler是代理实例的,调用处理程序实现的接口,每个代理实例都具有一个关联的调用处理程序,ze 代表需要实现InvocationHandler的接口,对代理实例调用方法时,将对方法调用进行编码并将指派到它的调用处理程序的invoke方法,public Object invoke(Object proxy, Method method, Object[] args)代表在代理实例上处理方法调用并返回结果
3.1 三部曲
- InvocationHandler 接口
- invoke方法
- Proxy.newProxyInstance();
3.2 Subject
public interface Subject {
public void sailBooks();
}
3.3 RealSubject
public class RealSubject implements Subject {
@Override
public void sailBooks() {
System.out.println("出版社卖书");
}
}
3.4 MyHandler,需要实现调用处理程序实现的接口,即InvocationHandler
public class MyHandler implements InvocationHandler {
private RealSubject realSubject;
public void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
//执行附属操作
this.discount();
//拦截realSubject中的方法
result = method.invoke(realSubject,args);
this.coupon();
return result;
}
//打折
public void discount(){
System.out.println("打折");
}
//代金券
public void coupon(){
System.out.println("赠与代金券");
}
}
3.5 MainClass
public class MainClass {
public static void main(String[] args){
RealSubject realSubject = new RealSubject();
MyHandler myHandler = new MyHandler();
myHandler.setRealSubject(realSubject);
Subject proxySubject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(),realSubject.getClass().getInterfaces(),myHandler);
proxySubject.sailBooks();
}
}