代理模式
代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,并且代理者执行功能时会附加一些额外的操作
如:手机工厂和代理商都具有卖东西的功能,手机代理商除了帮工厂卖手机外,还能在卖手机前打广告推销,卖手机后还可以进行售后服务。
代理模式的优点:
符合开闭原则,不用修改被代理者任何的代码,就能扩展新的功能
项目的扩展和维护比较方便
1、静态代理
角色分析:
- 抽象角色:一般使用接口或抽象类解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,一般会做一些附属操作
- 客户:访问代理对象的人
这里使用一个租房中介的案例:
抽象角色(接口):租房
//租房public interface Rent { void rent();}
真实角色:房东
//房东public class Host implements Rent{ public void rent() { System.out.println("房东要出租房"); }}
代理角色:中介所(通常包含附属的一些其他方法)
//代理类public class Agent implements Rent{ //组合由于继承 private Host host; public void setHost(Host host) { this.host = host; } public void rent(){ host.rent(); this.sign(); this.fare(); } //签合同 public void sign(){ System.out.println("中介签合同"); } //中介费 public void fare(){ System.out.println("收取中介费"); }}
客户端访问代理角色:
public class Client { public static void main(String[] args) { Host host = new Host(); Agent agent = new Agent(); agent.setHost(host); agent.rent(); }}
静态代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用关注一些公共的业务
- 公共业务就交给了代理角色,实现了业务的分工
- 公共业务发生拓展的时候,方便集中管理
缺点:
静态代理只能适合一种业务,如果有新的业务,就必须创建新的接口和新的代理
每个真实角色就会产生一个代理角色,代码量会翻倍;
AOP(面向切面编程)的实现原理就是代理模式:
1.对于切面织入的实现就是对业务接口创建了一个代理类,
2.代理类中组合了业务接口的实现类,
3.代理类在原先实现类的方法上添加了一些附属方法,
4.客户端访问时即能使用代理类的业务(包括初始业务以及拓展业务)。
这样就实现了对切面的织入,不需要改变原有代码而拓展了新的业务,符合开闭原则;
2、动态代理
动态代理的实现基于反射机制
角色和静态代理相同
动态代理的代理类是动态生成的,而不是直接写好的
动态代理分为两大类:基于接口的动态代理;基于类的动态代理
- 基于接口:JDK动态代理
- 基于类:cglib
- java字节码实现:javasist
需要了解两个类:
Proxy:代理
Proxy
提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
InvocationHandler接口:调用处理程序
InvocationHandler
是由代理实例的调用处理程序实现的接口。每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的
invoke
方法。
动态代理的特点:(在静态代理的基础上)
- 一个动态代理类代理的是一个接口,一般就是对应一类业务
- 一个动态代理类可以代理多个类,只要这些类实现了同一接口即可
java代码实现
需要被代理的接口:
public interface UserService { void add(); void delete(); void update(); void query();}
真实角色(实现类):
public class UserServiceImpl implements UserService { public void add() { System.out.println("add"); } public void delete() { System.out.println("delete"); } public void update() { System.out.println("update"); } public void query() { System.out.println("query"); }}
生成代理对象的调试处理类:
//这个类用于自动生成代理类public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Object target; public void setUserService(UserService userService) { this.target = userService; } //生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //处理代理实例,返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //通过反射得到调用的方法名 log(method.getName()); //调用方法 return method.invoke(target,args); } //代理类的一些附属方法 public void log(String s){ System.out.println("调用了"+s+"方法"); }}
客户端:
public class Client { public static void main(String[] args) { //真实类 UserServiceImpl userService = new UserServiceImpl(); //动态生成代理角色的处理类 ProxyInvocationHandler pih = new ProxyInvocationHandler(); //设置要代理的对象 pih.setUserService(userService); //生成代理实例 UserService proxy = (UserService) pih.getProxy(); // **当调用被代理角色的方法时,会通过反射机制调用代理类中的invoke方法 proxy.query(); }}
运行结果:
调用了query方法query
重点:代理对象必须是接口,以及proxy返回的也是接口的代理实例!!
代理模式的简单理解与使用farfetch、 c-tick认证、 丰趣海淘、 竞品Review分析,或许能给你的选品带来意外惊喜 、 一分钟教你速卖通直通车、 亚马逊广告SPD是什么?和PPC有什么区别?、 自驾车长途旅游要注意什么呢?、 去漂流应该怎么注意安全?、 放寒假了,学生寒假去哪里玩好?、
没有评论:
发表评论