定義:代理一個(gè)對象,去執(zhí)行對象的方法。
使用場景:根據(jù)開閉原則,很多時(shí)候我們不能去直接修改被代理的實(shí)現(xiàn)類,而又要增加業(yè)務(wù)邏輯,這時(shí)可以使用代理模式。
舉例:比如我們調(diào)用一個(gè)第三方接口的方法,現(xiàn)在有個(gè)新需求,在執(zhí)行某個(gè)方法前,需要記錄日志,我們無法修改第三方接口,這時(shí)可以使用代理模式。
優(yōu)點(diǎn):程序擴(kuò)展性、可維護(hù)性增強(qiáng),無需更改以前的實(shí)現(xiàn)。
1.? 靜態(tài)代理
對每一個(gè)需要被代理的類,新增一個(gè)代理類;
1.1 支付接口
public interface PayService {
????void pay();
}
1.2 被代理對象,實(shí)現(xiàn)支付接口
public class PayServiceImpl implements PayService{
? ? @Override
? ? public void pay() {
? ? ? ? System.out.println("支付完成");
? ? }
}
1.3 代理類,實(shí)現(xiàn)支付接口
public class StaticProxy implements PayService{
? ? private PayService payService;
? ? public StaticProxy(PayService payService) {
? ? ? ? this.payService = payService;
? ? }
? ? @Override
? ? public void pay() {
? ? ? ? System.out.println("支付日志記錄...");
? ? ????payService.pay();
? ? }
}
1.4 調(diào)用示例:
public class StaticProxyMain {
? ? public static void main(String[] args) {
? ? ? ? PayService payService = new PayServiceImpl();
? ? ? ? StaticProxy proxy = new StaticProxy(payService);
? ? ? ? proxy.pay();
? ? }
}
打印結(jié)果如下:
支付日志記錄...
支付完成
2.動(dòng)態(tài)代理
采用InvocationHandler實(shí)現(xiàn),InvocationHandler是一個(gè)JDK提供的標(biāo)準(zhǔn)接口。在動(dòng)態(tài)代理實(shí)現(xiàn)時(shí),無需指定被代理的類,在具體調(diào)用時(shí)再指定。
2.1 重寫代理類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler{
? ? private Object obj;
? ? public DynamicProxy(Object obj) {
? ? ? ? this.obj = obj;
? ? }
? ? @Override
? ? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
? ? ? ? Object result = method.invoke(this.obj, args);
? ? ? ? return result;
? ? }
}
2.2 調(diào)用示例
import java.lang.reflect.Proxy;
public class DynamicProxyMain {
? ? public static void main(String[] args) {
? ? ? ? PayService payService = new PayServiceImpl();
? ? ? ? DynamicProxy proxy = new DynamicProxy(new PayServiceImpl());
? ? ? ? PayService payServiceProxy = (PayService) Proxy.newProxyInstance(payService.getClass().getClassLoader(),? ? ? ? ????????????payService.getClass().getInterfaces(), proxy);
? ? ? ? System.out.println("支付日志記錄...");
? ? ? ? payServiceProxy.pay();
? ? }
}
打印結(jié)果和上面是一致的. 下面這段代碼返回PayService,但并不是PayServiceImpl的實(shí)例,而是JVM給我們加過工的,包含了我們在invoke方法里的實(shí)現(xiàn)。debug,payServiceProxy類型為$Proxy0
PayService payServiceProxy = (PayService) Proxy.newProxyInstance(payService.getClass().getClassLoader(), payService.getClass().getInterfaces(), proxy);