設計模式——代理模式

代理模式
爲其他對象提供一種代理以控制對這個對象的訪問,有時委託類不適合或不能直接引用另一個對象時,代理類就在兩方之間起到一個橋樑的作用。代理設計模式符合開閉原則 ,在不修改原有類的基礎上,增強原有類的功能邏輯。
代理模式優點:
增強真實對象
保護真是對象
降低系統耦合度,擴展性好
代理模式缺點
代理類使系統設計時的類增多
靜態代理: 一個接口,兩個類:真實業務類,代理類
靜態體現在:代理類和真實類的關係在程序運行前就確定了
在靜態代理的實現中,需要定義一個接口,真實業務類和代理類都要實現這個接口,同時在代理類中,要定義一個真實對象的引用,通過構造方法傳給代理類對象,然後在調用業務方法時,調用真實類的業務實現

//定義了業務的實現規範
interface Buy {
    void buyMac();
    void buyGivenchy();
}
//真實類(委託類)真實業務的實現
class Real implements Buy{

    @Override
    public void buyMac() {
        System.out.println("buy a mac");
    }

    @Override
    public void buyGivenchy() {
        System.out.println("buy a givenchy");
    }
}
//代理類  代理Real類蒐集有的功能,並做額外的增強
class ProxyClass implements Buy{
//引用接口對象使得代理類可以訪問實體
    private Buy buy;
    public ProxyClass(Buy buy){
        this.buy = buy;
    }
    //其實代理類的本質還是用了委託類的具體方法
    @Override
    public void buyMac() {
        System.out.println("買");
        this.buy.buyMac();
    }

    @Override
    public void buyGivenchy() {
        System.out.println("買");
        this.buy.buyGivenchy();
    }
}
public class ProxyDemo {
    public static void main(String[] args) {
        Buy buy = new ProxyClass(new Real());
        buy.buyMac();
        buy.buyGivenchy();
    }
}

靜態代理是效率最高效率的代理模式,但它也存在缺陷
**靜態代理缺陷:**每一個需要被代理的類或接口,都要爲其實現一個代理類,如果需要代理的類或接口很多,就導致要實現的代理類也很多,這時引入動態代理。動態代理是由一個代理類來代理所有需要被代理的類或接口
動態代理:
在程序運行時有JVM創建代理類,此時的這個代理類可以代理任何需要被代理的類或接口,動態體現在這裏
今天來說JDK代理:
JDK代理就是使用JDK內置的方法去實現代理模式,有兩個核心的類Proxy和InvocationHandle
Proxy:調度器
InvocationHandle:增強器

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException

有三個參數:
真是對象的類加載器
真是對象實現的接口
真實對象實例
實現動態代理:

interface ISubject{
    public void eat(int num,String msg);
}
//真是業務類
class RealImpl implements ISubject{

    @Override
    public void eat(int num,String msg) {
        System.out.println("I want to buy "+ num + msg);
    }
}
//實現InvocationHandler的代理類
class ProxySubject implements InvocationHandler{
    private Object target;

    public ProxySubject(){ }

    public Object bind(Object target){
        this.target = target;
        //通過JDK獲取代理類對象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);//此時的this是真實類的對象
    }

    public void preHandle(){
        System.out.println("before buy");
    }

    public void afterHandle() {
        System.out.println("after buy");
    }
//通過invoke方法對真是業務做增強以及調用真實業務
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.preHandle();
        Object obj = method.invoke(this.target,args);
        this.afterHandle();
        return obj;
    }
}
public class JDKProxyDemo {
    public static void main(String[] args) {

        ISubject subject = (ISubject) new ProxySubject().bind(new RealImpl());
//此時真實類與代理已經建立聯繫
        subject.eat(3,"apples");
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章