代理模式是什麼
代理模式是一種設計模式,簡單說即是在不改變源碼的情況下,實現對目標對象的功能擴展。
比如有個歌星對象叫RealStar,他十分會唱歌,但是這個歌手十分忙,他只想唱歌不願意做其他的事情,因此你需要幫助他完成任務!
Star接口
package com.Geeksun.proxy.dynamicProxy;
public interface Star {
void sign();
void payMoney();
void sing();
}
RealStar
package com.Geeksun.proxy.dynamicProxy;
public class RealStar implements Star {
@Override
public void sign() {
System.out.println("我不會!");
}
@Override
public void payMoney() {
System.out.println("我不會!");
}
@Override
public void sing() {
System.out.println("sing");
}
}
1.靜態代理
這時候有一個代理對象
package com.Geeksun.proxy.staticProxy;
public class ProxyStar implements Star{
private Star star;
public ProxyStar(Star star){
this.star = star;
}
@Override
public void sign() {
System.out.println("sign");
}
@Override
public void payMoney() {
System.out.println("payMoney");
}
@Override
public void sing() {
star.sing();
}
}
總結:其實這裏做的事情無非就是,創建一個代理類ProxyStar,繼承了Star接口並實現了其中的方法。只不過這種實現特意包含了目標對象的方法,正是這種特徵使得看起來像是“擴展”了目標對象的方法。假使代理對象中只是簡單地對sing方法做了另一種實現而沒有包含目標對象的方法,也就不能算作代理模式了。所以這裏的包含是關鍵。
缺點:這種實現方式很直觀也很簡單,但其缺點是代理對象必須提前寫出,如果接口層發生了變化,代理對象的代碼也要進行維護。如果能在運行時動態地寫出代理對象,不但減少了一大批代理類的代碼,也少了不斷維護的煩惱,不過運行時的效率必定受到影響。這種方式就是接下來的動態代理。
2.動態代理(也叫JDK代理)
跟靜態代理的前提一樣,依然是對Star對象進行擴展
StarHandler
package com.Geeksun.proxy.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class StarHandler implements InvocationHandler {
private Star star;
public StarHandler(Star star){
this.star = star;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
System.out.println("訂票");
if(method.getName().equals("sing")){
object = method.invoke(star,args);
}
System.out.println("收錢");
return object;
}
}
Client
package com.Geeksun.proxy.dynamicProxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
StarHandler starHandler = new StarHandler(new RealStar());
Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class},starHandler);
proxy.sign();
proxy.sing();
}
}
調用Proxy類的靜態方法newProxyInstance即可,該方法會返回代理類對象
|
接收的三個參數依次爲:
ClassLoader loader:
指定當前目標對象使用類加載器,寫法固定Class<?>[] interfaces:
目標對象實現的接口的類型,寫法固定InvocationHandler h
:事件處理接口,需傳入一個實現類,一般直接使用匿名內部類