1. 程式人生 > >校園愛情故事後記

校園愛情故事後記

Hi,我是十三,是不是越長大就更難做到堅持…

在這裡插入圖片描述

前言

  自從上次十三有了女神閨蜜的情報,十三最後是否成功抱得美人歸呢?這可能是個謎,因為寫這篇文章的十三自己都不知道呢,嘿嘿。好吧,說著說著話題都偏了…不知道十三在說啥的同學,請到傳送門接受安檢 十三校園泡妞記

  有了閨蜜的精準情報,十三每次自然不會撲空,只是當十三想要上去搭訕或是有進一步動作的時候,十三就慫了,沒錯,慫了。他害怕又感些許自卑,可又擔心這樣下去會失去,就這樣一直迴圈重複,就連臥底閨蜜都抱怨十三太慫了,嚷嚷著不提供情報了,可每次看到十三那一臉痴情樣又嘆了口氣。

  某天晚上,十三手捧著束花,他動作熟練地開啟手機微信,發了條資訊,上面寫著:“恩人阿恩人,我在你樓下幫我送束花給她吧,您的大恩大德永不忘!”,沒過多久,對方回信:“可以啊,還懂得送花了,開竅了,不過自己送。”,原來十三想送花給女神,可他又不好意思當面送,看來十三是真的慫…只好委託她閨蜜幫他送花了,只是人家並不答應他,最後還是十三提出請她吃大餐才答應送花的…

  注意,這裡開始可是要畫風突變了,上面這個委託送花過程其實可以用到個設計模式,它便是代理模式,好,接下來我們一起來看看代理模式的介紹。

代理模式 (Proxy)

  代理模式也被稱為委託模式,它是結構型設計模式的一種。在我們平時日常生活中類似代理模式的場景也非常常見,比如說請律師代理打官司、代理工具上網等等。

定義:為其他物件提供一種代理以控制對這個物件的訪問.

代理模式中的角色及職責 :

  • Subject : 抽象主題類,宣告真實主題與代理的共同介面方法.

  • RealSubject : 真實主題類,代理類所代表的真實主題,客戶端通過代理類間接地呼叫真實主題類的方法.

  • Proxy : 代理類,持有對真實主題類的引用,在其所實現的介面方法中呼叫真實主題類中相應的介面方法執行.

  學了就要用,接下來我們把上面十三委託送花的事用代理模式簡單實現下:

public interface GiveGift{

    public void GiveFlowers();

}

  首先我們先定義了一個抽象主題介面,抽象主題類它具有真實主題類和代理的共同介面方法,而這個共同方法就是送花了,所以在裡面提供了 GiveFlowers 這個方法,繼續往下看 :

public class Pursuit implements GiveGift {

    private String girlName;
    private String boyName;

    public
Pursuit(String girlName, String boyName) { this.girlName = girlName; this.boyName = boyName; } @Override public void GiveFlowers() { System.out.println(girlName + "," + boyName + "送你花耶!"); } }

  然後我們定義了個追求者類,它實現了抽象主題類並重寫接口裡面的方法,實際上,它是代理模式中真實主題類這個角色,在送花這裡十三無疑便是這個角色了。

public class Proxy implements GiveGift {

    private String proxyName;
    Pursuit pursuit;

    public Proxy(String proxyName, String girlName, String boyName) {
        this.proxyName = proxyName;
        pursuit = new Pursuit(girlName, boyName);
    }

    @Override
    public void GiveFlowers() {
        System.out.print(proxyName + ":");
        pursuit.GiveFlowers();
    }

}

  接下來就是代理類了,它同樣也是實現了抽象主題介面,我們可以看到它持有對真實主題類的引用,並在重寫的介面方法中呼叫真實主題類重寫的介面方法,也就是說,閨蜜代理幫十三完成送花這個動作,之所以通過呼叫真實主題類重寫的方法,是因為這是十三委託我們的閨蜜幫他送花。

public class Client {

    public static void main(String[] args) {
        Subject proxy = new Proxy("LL閨蜜", "LL", "十三");
        proxy.GiveFlowers();
    }
}
LL閨蜜:LL,十三送你花耶!

  客戶端的程式碼非常簡單,我們直接通過代理物件並呼叫相關方法就完成了送花這個動作,最終呼叫的是真實主題類裡實現的方法,我們這裡就成功使用代理模式做了個簡單實現。

  事實上上面我們寫的例子是靜態代理,代理模式主要分為靜態代理和動態代理。靜態代理在程式碼執行前就已經存在了代理類的 class 編譯檔案;動態代理則是在執行時通過反射來動態生成代理類的物件,並確定是誰來代理。

動態代理

  既然靜態代理我們上面已經實現過了,那麼這個動態代理應該怎麼來做呢?別急,JDK 提供了相關的類庫供我們使用,InvocationHandler 是代理例項的呼叫程式實現的介面,實現了該介面需要重寫 invoke() 方法,那麼下面我們用十三送花這個例子來實現動態代理 :

public class DynamicProxy implements InvocationHandler {

    private Object object;

    public DynamicProxy(Object object) {
        this.object = object;
    }

    // 在代理例項上處理方法呼叫並返回結果
    @Override
    public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable {
        Object result = method.invoke(object, arg);
        return result;
    }

}

  首先我們先聲明瞭一個 Object 物件,它指向引用與真實主題類,也就是被代理類,緊接著我們在重寫的 invoke 方法中去呼叫執行被代理類的具體方法。

public class Client {

    public static void main(String[] args) {

        Subject realSubject = new Pursuit("LL", "十三");
        DynamicProxy mDynamicProxy = new DynamicProxy(realSubject);
        ClassLoader loader = Pursuit.class.getClassLoader();
        Subject dynamicProxy = (Subject) java.lang.reflect.Proxy.
                newProxyInstance(loader, new Class[]{Subject.class}, mDynamicProxy);
        dynamicProxy.GiveFlowers();
    }

}

  最後我們得要在客戶端呼叫 Proxy.newProxyInstance() 方法來生成動態代理類,接著通過它去呼叫 GiveFlowers() 方法,而它則會去呼叫上面我們寫的 DynamicProxy 類中的 invoke 方法,這樣我們便簡單完成了動態代理。

LL,十三送你花耶!
## 總結 ##

  那麼到最後我們來簡單總結下 :

使用場景 (通過網路搜尋,一般分下面幾種):

  • 遠端代理,也就是為一個物件在不同的地址空間提供區域性代表,這樣便於隱藏.

  • 虛擬代理,根據需要建立開銷很大的物件,通過它來存放例項化需要很長時間的真實物件.

  • 安全代理,用來控制真實物件訪問時的許可權.

  • 智慧指引,當呼叫真實物件時,代理處理另外一些事.

優點 :

  • 真實主題類只需關心本職工作.

  • 即使真實主題類發生變化,代理類仍然不受影響,因為真實主題類實現了公共介面.

這裡來張代理模式的合照,一 二 三,茄子 :

在這裡插入圖片描述

後話

  後來,LL 收到了十三送的花,其實 LL 知道十三喜歡她,因為閨蜜已經把什麼都和她說了…LL 拿著花並輕輕說了句:“呆子!“。我 TM 編故事真累…