代理模式


代理對象

在有些情況下,一個客戶不能或者不想直接訪問另一個對象,這時需要找一個中介幫忙完成某項任務,這個中介就是代理對象。

需求

  • 電腦廠商
  • 電腦代理商

角色

抽象主題(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();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM