2020年8月12日星期三

代理模式的简单理解与使用

代理模式

代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,并且代理者执行功能时会附加一些额外的操作

如:手机工厂和代理商都具有卖东西的功能,手机代理商除了帮工厂卖手机外,还能在卖手机前打广告推销,卖手机后还可以进行售后服务。

代理模式的优点:

  • 符合开闭原则,不用修改被代理者任何的代码,就能扩展新的功能

  • 项目的扩展和维护比较方便

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返回的也是接口的代理实例!!

代理模式的简单理解与使用farfetchc-tick认证丰趣海淘竞品Review分析,或许能给你的选品带来意外惊喜 一分钟教你速卖通直通车亚马逊广告SPD是什么?和PPC有什么区别?自驾车长途旅游要注意什么呢?去漂流应该怎么注意安全?放寒假了,学生寒假去哪里玩好?

没有评论:

发表评论