代理對象
在有些情況下,一個客戶不能或者不想直接訪問另一個對象,這時需要找一個中介幫忙完成某項任務,這個中介就是代理對象。
需求
- 電腦廠商
- 電腦代理商
角色
抽象主題(Subject)類
通過接口或抽象類聲明真實主題和代理對象實現的業務方法。
真實主題(Real Subject)類
實現了抽象主題中的具體業務,是代理對象所代表的真實對象,是最終要引用的對象。
代理(Proxy)類
提供了與真實主題相同的接口,其內部含有對真實主題的引用,它可以訪問、控制或擴展真實主題的功能。
UML 圖

靜態代理
寫法:

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 圖

動態代理
動態代理與靜態代理的區別
靜態
由程序員創建代理類或特定工具自動生成源代碼再對其編譯,在程序運行前代理類的 .class 文件就已經存在了。
動態
在程序運行時,運行反射機制動態創建而成,運行時,生成的字節碼,類加載器,通過反射創建對象。
JDK 動態代理
Java 中提供了一個動態代理類 Proxy,Proxy 給提供了一個創建代理對象的靜態方法(newProxyInstance方法)來獲取代理對象。

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

/**
* @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("華為總公司銷售!");
}
}

/**
* @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;
});
}
}

/**
* @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("華為總公司銷售!");
}
}

/**
* @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;
}
}

/**
* @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();
}
}
