JAVA設計模式理解與總結(下)代理模式&適配器模式&觀察者模式

碼了好幾年代碼的打字機器我,對于設計模式這個詞,肯定是一點也不陌生,但是對于設計模式的理解,因為日常開發(fā)中,增刪改查較多,使用設計模式思想來優(yōu)化代碼的機會就很少。也不乏在翻閱源碼的時候,嘆服于別人優(yōu)秀高效的設計。所有今天抽出點時間,對設計模式做個歸納、記錄,以便日后讀到優(yōu)秀的源碼,可以自信的說,這**不就是那啥嗎,我也會寫~~~

設計模式

設計模式(Design Pattern)是前輩們對代碼開發(fā)經(jīng)驗的總結,是解決特定問題的一系列套路。它不是語法規(guī)定,而是一套用來提高代碼可復用性、可維護性、可讀性、穩(wěn)健性以及安全性的解決方案

代理模式

一個類代表另一個類的功能,在代理模式中,我們創(chuàng)建具有現(xiàn)有對象的對象,以便向外界提供功能接口。

代理模式在我們的生活中也很常見,例如程序員的女友想買一個法國產(chǎn)的某包包,她不需要親自去法國某個賣驢的專賣店去買,而是可以在代購手中購買,并獲得一些小禮物,折扣優(yōu)惠等等。

靜態(tài)代理

在代碼中,代理就是在使用者和服務提供者中間的服務,提供一些在提供的服務前后處理一些事物的功能。

賣東西人的認證(共同實現(xiàn)的接口)

public interface Seller {
    void sell();
}

法國某經(jīng)銷商:

public class LvFactory implements Seller{
    @Override
    public void sell() {
        System.out.println("LV廠家賣包包");
    }
}

你女朋友朋友圈某個不知名好友:

class Purchase implements Seller{
    private Seller seller;

    public Purchase(Seller factory) {
        this.seller = factory;
    }

    @Override
    public void sell() {
        System.out.println("坐飛機去法國");
        seller.sell();
        System.out.println("坐飛機回國");
    }
}

你女朋友:

public static void main(String[] args) {
    Seller lv = new LvFactory();
    new Purchase(lv).sell();
}

你:

信用卡 boom~~~~~~~~~~~~~~~~~

坐飛機去法國

LV廠家賣包包

坐飛機回國

動態(tài)代理

動態(tài)代理有別于靜態(tài)代理,是根據(jù)代理的對象,動態(tài)創(chuàng)建代理類。這樣,就可以避免靜態(tài)代理中代理類接口過多的問題。動態(tài)代理是實現(xiàn)方式,是通過反射來實現(xiàn)的,借助Java自帶的java.lang.reflect.Proxy,通過固定的規(guī)則生成。

舉個??,女朋友朋友圈這個代購,代購包,也代購手表,那我找他一起買一塊手表呢?

手表接口和天梭類:

public interface Watch {
    void sellWatch();
}
public class TissotWatch implements Watch {
    @Override
    public void sellWatch() {
        System.out.println("賣天梭手表");
    }
}

使用 InvocationHandler 定義代理類:

public class PurchaseProxy implements InvocationHandler {
    private Object object;
    public PurchaseProxy(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("坐飛機出國");
        Object result = method.invoke(object, args);
        System.out.println("坐飛機回國");
        return result;
    }
}

在朋友圈買包買表:

public static void main(String[] args) {
    //賣包
    Seller lvseller = new LvFactory();
    PurchaseProxy lvproxy = new PurchaseProxy(lvseller);
    ((Seller) Proxy.newProxyInstance(lvseller.getClass().getClassLoader(), new Class[] { Seller.class }, lvproxy)).sell();
    //賣表
    Watch tissot = new TissotWatch();
    PurchaseProxy tissotproxy = new PurchaseProxy(tissot);
    ((Watch) Proxy.newProxyInstance(tissot.getClass().getClassLoader(), new Class[] { Watch.class }, tissotproxy)).sellWatch();
}

坐飛機出國

LV廠家賣包包

坐飛機回國

坐飛機出國

賣天梭手表

坐飛機回國

動態(tài)代理詳解

InvocationHandler

InvocationHandler 是一個接口,當代理方法被調(diào)用時,會調(diào)用起相對應的實現(xiàn)類的 invoke 方法。

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    return null;
}

三個參數(shù):

  • proxy 代理對象
  • method 代理對象調(diào)用的方法
  • args 調(diào)用的方法中的參數(shù)
Proxy

Java自帶的java.lang.reflect.Proxy

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
  • loader 類加載器
  • interfaces 代碼要用來代理的接口
  • h 一個 InvocationHandler 對象

適配器模式

我們?nèi)粘J褂玫倪m配器是一個接口轉換器,它可以是一個獨立的硬件接口設備,允許硬件或電子接口與其它硬件或電子接口相連,也可以是信息接口

在代碼中,我想實現(xiàn)一個接口中的部分功能,或者想用一個類來冒充另一個類來實現(xiàn)它的功能,就需要適配器模式了。

適配器模式使接口不兼容的那些類可以一起工作,其別名為包裝器

類適配器模式

在類適配器模式中,適配器與適配者之間是繼承,適配著實現(xiàn)通用接口

舉個??,我國標準電壓是220v,手機充電器也是220v,日本標準電壓是110v,女朋友去日本玩,想給220v的手機用110v電壓充電,就需要一個適配器了。

日本插座:

public class JapanAC {
    private final static int v = 110;
    public void jcharge() {
        System.out.printf("使用%dv電壓充電\n", v);
    }
}

充電通用接口:

public interface Charger {
    void charge();
}

買一個 110v升220變壓器:

public class Adaptee extends JapanAC implements Charger {
    @Override
    public void charge() {
        System.out.println("使用適配器110v轉220v");
        super.jcharge();
        System.out.println("充電完成");
    }
}

女朋友使用適配器充電:

public static void main(String[] args) {
    Charger charger = new Adaptee();
    charger.charge();
}

使用適配器110v轉220v

使用110v電壓充電

充電完成

對象適配器模式

把一只猴子偽裝成人:

有那么一種猴子:

public interface Monkey {
    //吃香蕉
    void eatBanana();
    //騎獨輪車
    void rideABike();
}
public class Shuang implements Monkey {
    @Override
    public void eatBanana() {
        System.out.println("猴子吃香蕉");
    }
    @Override
    public void rideABike() {
        System.out.println("猴子獨輪車"); //猴子不懂人性,只會騎獨輪車
    }
}

有那么個人:

public interface Human {
    //吃香蕉
    void eatBanana();
    //開車
    void drive();
}
public class Da implements Human{
    @Override
    public void eatBanana() {
        System.out.println("人吃香蕉");
    }
    @Override
    public void drive() {
        System.out.println("人開車");
    }
}

猴子偽裝成人的大型真猴修表演:

public class MonkeyMan implements Human{
    private Monkey monkey;
    public MonkeyMan(Monkey monkey) {
        this.monkey = monkey;
    }
    @Override
    public void eatBanana() {
        monkey.eatBanana();
    }
    @Override
    public void drive() {
        monkey.rideABike();
    }
}

猴子偽裝成人:

public static void main(String[] args) {
    Monkey shuang = new Shuang();
    Human human = new MonkeyMan(shuang); //猴子成人
    human.drive();
}

猴子獨輪車

觀察者模式

當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。

又被稱為發(fā)布-訂閱(Publish/Subscribe)模式

例如微博關注,多個用戶關注同一博主,博主更新,會通知到所有用戶。

羅老師微博:

public interface Bloger {
    void add(Fan fan);
    void del(Fan fan);
    void notifySms(String sms);
}
public class Luo implements Bloger {
    private List<Fan> fans;
    {
        fans = new ArrayList<>();
    }
    @Override
    public void add(Fan fan) {
        fans.add(fan);
    }
    @Override
    public void del(Fan fan) {
        fans.remove(fan);
    }
    @Override
    public void notifySms(String sms) {
        fans.forEach(fan -> fan.notifySms(sms));
    }
}

粉絲:

public interface Fan {
    void notifySms(String sms);
}
public class Xigua implements Fan {
    private String name;
    public Xigua(String name) {
        this.name = name;
    }
    @Override
    public void notifySms(String sms) {
        System.out.println(name + " | " + sms);
    }
}

羅老師直播買手機 :

public static void main(String[] args) {
    Fan leijun = new Xigua("雷軍");
    Fan dongmingzhu = new Xigua("董明珠");
    Fan renzhengfei = new Xigua("任正非");

    Bloger luo = new Luo();
    luo.add(leijun);
    luo.add(dongmingzhu);
    luo.add(renzhengfei);

    luo.notifySms("買錘子,送錘子啦?。?!");
}

雷軍 | 買錘子,送錘子啦?。?!

董明珠 | 買錘子,送錘子啦?。?!

任正非 | 買錘子,送錘子啦?。?!

實際生產(chǎn)過程中,觀察者模式往往用消息中間件來實現(xiàn)

收工





更多好玩好看的內(nèi)容,歡迎到我的博客交流,共同進步????????WaterMin


?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容