代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
理解:
就这么举个例子把。比如我们网购。我们是直接从淘宝上买东西,而不是去实体店。淘宝这个平台就是一个代理。我们只要在网上买好东西,淘宝、快递就会帮我们送过来。
代理模式是对一个方法的加强,可以在这个方法执行的前后加上动作。比如权限的控制、日志的管理都是用到了代理模式这个原理。
优点
编辑
(1).职责清晰
真实的角色就是实现实际的
业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
(3).高扩展性
组成:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
静态代理:
抽象角色->
package yyf.designpatterns.proxy; /** * 抽象主题,定义主要功能 */ public interface Subject { public void operate(); }
真实角色->
package yyf.designpatterns.proxy; /** * 具体主题 */ public class RealSubject implements Subject { @Override public void operate() { System.out.println("real subject operate started......"); } }
代理角色->
package yyf.designpatterns.proxy; import java.lang.reflect.Method; /** * 动态代理类 * * @author Yu Yufeng * */ public class ProxyHandler { private Object proxied; public ProxyHandler(Object proxied) { this.proxied = proxied; } public String invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在转调具体目标对象之前,可以执行一些功能处理 System.out.println("before"); // 转调具体目标对象的方法 method.invoke(proxied, args); // 在转调具体目标对象之后,可以执行一些功能处理 System.out.println("after"); return this.toString(); } }
测试->
package yyf.designpatterns.proxy; /** * 静态代理测试 * * @author Yu Yufeng * */ public class Test { public static void main(String[] args) { Subject subject = new RealSubject(); Proxy proxy = new Proxy(subject); proxy.operate(); } } /** * 运行结果: * before operate...... * real subject operate started...... * after operate...... */
我们可以发型静态代理模式对一个类进行代理必须让真实代理类实现抽象接口。这样对代码就具有侵入性。所以,来看下动态代理。下面是一个简单的动态代理的代理类代码
package yyf.designpatterns.proxy; import java.lang.reflect.Method; /** * 动态代理类 * * @author Yu Yufeng * */ public class ProxyHandler { private Object proxied; public ProxyHandler(Object proxied) { this.proxied = proxied; } public String invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在转调具体目标对象之前,可以执行一些功能处理 System.out.println("before"); // 转调具体目标对象的方法 method.invoke(proxied, args); // 在转调具体目标对象之后,可以执行一些功能处理 System.out.println("after"); return this.toString(); } }
动态代理的测试类
package yyf.designpatterns.proxy; /** * 动态代理测试 * * @author Yu Yufeng * */ public class Test2 { public static void main(String[] args) throws Throwable { Subject subject = new RealSubject(); ProxyHandler proxy = new ProxyHandler(subject); proxy.invoke(proxy, Subject.class.getMethod("operate"), new Object[] {}); } }输出结果:
before
real subject operate started......
after
在我看来,动态代理无非就是通过反射对一个类进行加强。我们在调用真实主题的时候,就是通过反射得到了其中的方法,反射中传参数。虽然反射效率低了一点,但是这样可以做到不用修改原来的真实类,真正做到无侵入。
代码地址:https://github.com/yyfyyf1994/knowledge/tree/master/src/yyf/designpatterns/proxy