代理模式UML图
从UML图中,可以看出代理类与真正实现的类都是继承了抽象的主题类,这样的好处在于代理类可以与实际的类有相同的方法,可以保证客户端使用的透明性。
静态代理:
//抽象主题角色 真实主题与代理主题的共同接口
public interface Subject {
public void sailBook();
}
//真实主题角色 定义了代理角色所代表的的真实对象
public class RealSubject implements Subject {
@Override
public void sailBook() {
System.out.println("卖书");
}
}
public class ProxySubject implements Subject{
private RealSubject realSubject;
/*public void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
*/
@Override
//代理角色将客户端调用传递给真实主题前后还执行其他操作
public void sailBook() {
dazhe();
/*this.realSubject.sailBook();*/
if(realSubject == null){
realSubject = new RealSubject();
realSubject.sailBook();
}
give();
}
public void dazhe() {
System.out.println(" 打折");
}
public void give() {
System.out.println("赠送代金券");
}
}
public class Mainclass {
public static void main(String[] args) {
//RealSubject realSubject = new RealSubject();
/*realSubject.sailBook();*/
ProxySubject proxySubject = new ProxySubject();
//proxySubject.setRealSubject(realSubject);
proxySubject.sailBook();
}
}
通过上面的代理代码,我们可以看出代理模式的特点,代理类接受一个Subject接口的对象,任何实现该接口的对象,都可以通过代理类进行代理,增加了通用性。但是也有缺点,每一个代理类都必须实现一遍委托类(也就是realsubject)的接口,如果接口增加方法,则代理类也必须跟着修改。其次,代理类每一个接口对象对应一个委托对象,如果委托对象非常多,则静态代理类就非常臃肿,难以胜任。
动态代理:
实现步骤:
- 编写一个委托类的接口,即静态代理的(Subject接口)
- 实现一个真正的委托类,即静态代理的(RealSubject类)
- 创建一个动态代理类,实现
InvocationHandler
接口,并重写该invoke
方法 - 在测试类中,生成动态代理的对象。
//抽象主题角色 真实主题与代理主题的共同接口
public interface Subject {
public void sailBook();
}
//真实主题角色 定义了代理角色所代表的的真实对象
public class RealSubject implements Subject {
@Override
public void sailBook() {
System.out.println("卖书");
}
}
public class MyHandle implements InvocationHandler {
private RealSubject realSubject;
public void setRealSubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {
Object result = null;
dazhe();
result = method.invoke(realSubject, arg2);
give();
return result;
}
private void give() {
System.out.println("赠送代金卷");
}
private void dazhe() {
System.out.println("打折");
}
}
public class Mainclass {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
MyHandle myHandle = new MyHandle();
myHandle.setRealSubject(realSubject);
Subject proxySubject = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
realSubject.getClass().getInterfaces(), myHandle);
proxySubject.sailBook();
}
}
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理。在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样对每一个方法或方法组合进行处理。