ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

代理模式

2021-05-31 07:01:30  阅读:146  来源: 互联网

标签:Landlord void 代理 模式 rent landlord public


动态代理

  • 动态代理是动态生成的,不是我们直接写好的。
  • 动态代理分为两大类:基于接口的动态代理、基于类的动态代理
    • 基于接口:JDK动态代理【这章只讲这个】
    • 基于类:cglib
    • java字节码实现:javassist

需要了解两个类

  • Proxy【代理】
  • InvocationHandler【调用处理程序】

Pros:

  • 包括所有静态代理的所有好处
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口即可

================================== 分隔线 ===================================

https://www.cnblogs.com/daniels/p/8242592.html

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:

为什么要用代理模式?

  • 中介隔离作用 --> 在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 开闭原则,增加功能 --> 代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

分类

按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。

  • 静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。

  • 动态代理是在程序运行时通过反射机制动态创建的。(在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK再运行时为我们动态的来创建。)

静态代理

原先房东亲自出租房子

// 租房
public interface Rent {
    void rent();
}
// 房东
public class Landlord implements Rent {
    public void rent() {
        System.out.println("房东出租房子");
    }
}
// 房东亲自出租房子
public static void main(String[] args) {
    Landlord landlord = new Landlord();
    landlord.rent();
}

让代理出租房子

// 代理
public class Proxy implements Rent {
    private final Landlord landlord;

    public Proxy(Landlord landlord) {
        this.landlord = landlord;
    }

    // 代理帮助房东租房,并且还可以在租房的基础上增强一些功能
    public void rent() {
        System.out.println("代理打广告推销房子");
        landlord.rent();
    }
}
// 让代理出租房子
public static void main(String[] args) {
    Landlord landlord = new Landlord();
    Proxy proxy = new Proxy(landlord);
    proxy.rent();
}

Pros:

  • 可以做到在不修改目标对象的功能前提下,对目标功能扩展。
  • 真实角色更集中开发,不用去管一些公共业务。
  • 公共业务交给代理角色,实现业务分工。

Cons:

  • 代理角色要与真实角色实现一样的接口,代码量多,维护困难。
  • 同时,一旦接口增加方法,目标对象与代理对象都要维护。

动态代理

例子1

public interface Rent {
    void rent();
}
public class Landlord implements Rent {
    public void rent() {
        System.out.println("房东出租房子");
    }
}
import java.lang.reflect.*;

public class ProxyLandlord implements InvocationHandler {

    // 被代理的接口
    private final Rent rent;

    // 设置要被代理的角色
    public ProxyLandlord(Rent rent) {
        this.rent = rent;
    }

    // 生成得到代理类
    public Object getProxy() {
        // 第一个参数:ClassLoader
        // 第二个参数:an array of interfaces implemented by this class.
        // 第三个参数:调用处理程序
//        loader:被代理的类的类加载器;
//        interfaces:被代理类的接口数组;
//        invocationHandler:调用处理器类的对象实例。
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(), this);
    }

//    proxy:被代理的类的实例;
//    method:调用被代理的类的方法;
//    args:该方法需要的参数。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("帮房东打广告");
        Object result = method.invoke(rent, args);
        System.out.println("帮房东收费");
        return result;
    }

}

测试代码

public static void main(String[] args) {
    Landlord landlord = new Landlord();
    ProxyLandlord proxyLandlord = new ProxyLandlord(landlord);
    Rent r = (Rent) proxyLandlord.getProxy();
    r.rent();
}

结果

帮房东打广告
房东出租房子
帮房东收费

例子2

public interface Rent {
    void rent();
}
public class Landlord implements Rent {
    public void rent() {
        System.out.println("房东出租房子");
    }
}
public class DynamicProxy implements InvocationHandler {

    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                object.getClass().getInterfaces(),this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        this.log(method.getName());    // 使用反射获取方法的名字
        return result;
    }

    // 例如代理要添加功能
    public void log(String function) {
        System.out.println("房子被" + function + "了");
    }

}
public static void main(String[] args) {
    Landlord landlord = new Landlord();
    DynamicProxy dynamicProxy = new DynamicProxy();
    // 设置代理对象
    dynamicProxy.setObject(landlord);
    // 获取代理实例
    Rent proxy = (Rent) dynamicProxy.getProxy();
    // 调用实例方法
    proxy.rent();
}

测试结果

房东出租房子
房子被rent了

标签:Landlord,void,代理,模式,rent,landlord,public
来源: https://www.cnblogs.com/jumpig/p/14829878.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有