java设计模式(十二)代理模式
目录
- 定义
- 模式结构
- 角色职责
- 代码实现
- 静态代理
- 动态代理
- jdk动态代理
- cglib代理
- 适用场景
- 优缺点
定义
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。说简单点,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
模式结构
角色职责
1.抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
2.代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
3.真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
代码实现
代理模式属于结构性模式,有静态代理和动态代理。
静态代理是由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
静态代理
抽象角色
public interface Subject {void Request();
}
代理角色
public class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void Request() {if (realSubject == null) {realSubject = new RealSubject();}preRequest();realSubject.Request();postRequest();}public void preRequest() {System.out.println("访问真实主题之前的预处理");}public void postRequest() {System.out.println("访问真实主题之后的后续处理");}
}
真实角色
public class RealSubject implements Subject {@Overridepublic void Request() {System.out.println("访问真实主题方法");}
}
动态代理
jdk动态代理
抽象角色
public interface Animal {void eat();void sleep();
}
代理角色
public class JDKDynamicProxy implements InvocationHandler {private Object bean;public JDKDynamicProxy(Object bean) {this.bean=bean;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodname = method.getName();if (methodname.equals("eat")){System.out.println("吃饭了~~~");}else if(methodname.equals("sleep")){System.out.println("睡觉了~~~");}return method.invoke(bean,args);}
}
真实角色
public class Cat implements Animal {private String name;public Cat() {}public Cat(String name) {this.name = name;}@Overridepublic void eat() {System.out.println("喵喵"+name+"早晨吃饭了");}@Overridepublic void sleep() {System.out.println("喵喵"+name+"晚上睡觉啦");}
}
测试类
public class TestJDKDynamicProxy {public static void main(String[] args) {JDKDynamicProxy proxy = new JDKDynamicProxy(new Cat("喵喵"));Animal cat = (Animal) Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[]{Animal.class}, proxy);cat.eat();cat.sleep();}
}
cglib代理
代理角色
public class CglibProxy implements MethodInterceptor {private Enhancer enhancer=new Enhancer();private Object bean;public CglibProxy(Object bean) {this.bean = bean;}public Object getProxy(){//设置需要创建子类的类enhancer.setSuperclass(bean.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {String methodName = method.getName();if (methodName.equals("eat")){System.out.println("吃饭了~~~");}else if(methodName.equals("sleep")){System.out.println("睡觉了~~~");}return method.invoke(bean,objects);}
}
测试类
public class TestCglibProxy {public static void main(String[] args) {CglibProxy proxy = new CglibProxy(new Cat("喵喵"));Cat cat = (Cat) proxy.getProxy();cat.wakeup();cat.sleep();}
}
适用场景
代理模式可以在代理对象将请求转发给真实对象之前及之后可以执行操作,这使得代理模式应用场景非常广泛,如权限校验、日志记录,以及缓存等等,以及把一些重复代码使用代理模式进行重构提取。
优缺点
优点:
1.代理模式能将代理对象与真实被调用的目标对象隔离
2.一定程度上降低了系统的耦合度,扩展性好
3.可以起到保护目标对象的作用
4.可以对目标对象的功能增强
缺点:
1.代理模式会造成系统设计中类的数量增加
2.在客户端与目标对象之间增加一个代理对象,会造成请求处理速度变慢
3.增加了系统的复杂度