代理模式

代理对象

在有些情况下,一个客户不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象。

需求

  • 电脑厂商
  • 电脑代理商

角色

抽象主题(Subject)类

通过接口或抽象类声明真实主题和代理对象实现的业务方法。

真实主题(Real Subject)类

实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。

代理(Proxy)类

提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

UML 图

image-20211011191840030

静态代理

写法:

image-20210926104239153

SaleInterface.java

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:08
 * @description 代理协议,抽象主题
 **/
public interface SaleInterface {
    /**
     * 出售
     */
    void sale();
}

HuaWeiComputerFirm.java

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:09
 * @description 总公司类
 **/
public class HuaWeiComputerFirm implements SaleInterface {
    @Override
    public void sale() {
        System.out.println("华为总公司销售!");
    }
}

ComputerProxy.java

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:10
 * @description 代理商
 **/
public class ComputerProxy implements SaleInterface {

    private final SaleInterface saleInterface;

    public ComputerProxy(SaleInterface saleInterface) {
        this.saleInterface = saleInterface;
    }

    @Override
    public void sale() {
        System.out.println("加价!");
        this.saleInterface.sale();
        System.out.println("保修!");
    }
}

Client.java

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:13
 * @description
 **/
public class Client {
    public static void main(String[] args) {
        ComputerProxy computerProxy = new ComputerProxy(new HuaWeiComputerFirm());
        computerProxy.sale();
    }
}

UML 图

image-20210926104312789

动态代理

动态代理与静态代理的区别

静态

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

动态

在程序运行时,运行反射机制动态创建而成,运行时,生成的字节码,类加载器,通过反射创建对象。

JDK 动态代理

Java 中提供了一个动态代理类 Proxy,Proxy 给提供了一个创建代理对象的静态方法(newProxyInstance方法)来获取代理对象。

image-20210926112717494

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:08
 * @description 代理协议,抽象主题
 **/
public interface SaleInterface {
    /**
     * 出售
     */
    void sale();
}

image-20210926112817612

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:09
 * @description 总公司类
 **/
public class HuaWeiComputerFirm implements SaleInterface {
    @Override
    public void sale() {
        System.out.println("华为总公司销售!");
    }
}

image-20210926112859151

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:19
 * @description
 **/
public class ProxyFactory {
    public SaleInterface getComputerProxy(SaleInterface saleInterface) {
        return (SaleInterface) Proxy.newProxyInstance(
                saleInterface.getClass().getClassLoader(),
                saleInterface.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("加价");
                    Object invoke = method.invoke(saleInterface);
                    System.out.println("保修");
                    return invoke;
                });
    }
}

image-20210926112922990

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:23
 * @description
 **/
public class Client {
    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory();
        SaleInterface computerProxy = proxyFactory.getComputerProxy(new HuaWeiComputerFirm());
        computerProxy.sale();
    }
}

注意事项:JDK 动态代理要求必须定义接口,对接口进行代理。

CGLIB 动态代理

CGLIB 是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为 JDK 的动态代理提供了很好的补充,它是一个三方提供的包,maven 依赖坐标如下:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

SaleInterface.java

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:08
 * @description 代理协议,抽象主题
 **/
public interface SaleInterface {
    /**
     * 出售
     */
    void sale();
}

HuaWeiComputerFirm.java

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:09
 * @description 总公司类
 **/
public class HuaWeiComputerFirm implements SaleInterface {
    @Override
    public void sale() {
        System.out.println("华为总公司销售!");
    }
}

image-20210926113410726

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:35
 * @description
 **/
public class ProxyFactory<T> implements MethodInterceptor {

    private T computerProxy;

    public T getProxyObject(T computerProxy) {
        this.computerProxy = computerProxy;

        Enhancer enhancer = new Enhancer();

        // 设置父类字节码
        enhancer.setSuperclass(computerProxy.getClass());

        // 设置回调方法
        enhancer.setCallback(this);
        return (T) enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("加价");
        Object invoke = method.invoke(computerProxy, objects);
        System.out.println("保修");
        return invoke;
    }
}

image-20210926113426326

/**
 * @author BNTang
 * @program design-pattern-pro
 * @date Created in 2021/10/12 012 9:39
 * @description
 **/
public class Client {
    public static void main(String[] args) {
        ProxyFactory<SaleInterface> proxyFactory = new ProxyFactory<>();

        SaleInterface proxyObject = proxyFactory.getProxyObject(new HuaWeiComputerFirm());
        proxyObject.sale();
    }
}
posted @ 2021-09-26 10:45  BNTang  阅读(309)  评论(2编辑  收藏  举报