設計模式之結構型模式總結 - Structural Patterns

前言

本篇依然使用Java作為核心語言來總結<u>結構型模式</u>, 重點使用UML類圖以減少來回切換代碼而引起的邏輯混亂性.

完整代碼已上傳至GitOSC

適配器模式 - Adapter

適配器模式是將其他接口的功能進行轉換, 本質是轉調已有功能. 相對于裝飾者模式, 適配器模式轉換后的接口會變, 裝飾者則保持同一個接口, 所以裝飾者模式適合遞歸.

下面是將Android手機適配為假iPhone的例子

UML

適配器模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        // 我們有一臺普通的安卓手機
        final AndroidPhone androidPhone = new AndroidPhone();
        // 被奸商拿去改成iPhone騙小白
        final IPhoneAdaptor iPhone = new IPhoneAdaptor(androidPhone);
        // 視頻通話時瑪德黑屏
        iPhone.videoCall();
    }
}

橋接模式 - Bridge

維基上的對該模式的描述如下

Decouple an abstraction from its implementation allowing the two to vary independently.

讀起來不太像人話, "從實現部分解耦出抽象部門, 使他們可以獨立變化"

其實我們平常寫的Service, ServiceImpl就是橋接模式. 橋接模式適合控制多種變量, 例如"中國人發短信", "中國發郵件", "美國人發短信", "美國人發郵件". 這里有兩個變量"人"和"發布信息的方式", 這樣就抽象成兩個Service了.

UML

橋接模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final MessageService messageService = new EmailMessageService();
        final UserService userService = new ChineseService(messageService);
        userService.giveBirth();
    }
}

裝飾者模式 - Decorator

裝飾者模式主要功能是以動態的透明的方式給對象添加職責, 如增強功能, 控制訪問

下面是對MacBook添加Touch Bar并添加顏色Space Grey的例子

UML

裝飾者模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final MacBook macBook = new MacBook();
        final TouchBarDecorator greyMacBook = new TouchBarDecorator(macBook);
        final SpaceGreyDecorator touchBar = new SpaceGreyDecorator(greyMacBook);
        System.out.println(touchBar.feature());
    }
}

外觀模式 - Facade

為多個組件提供一個同一的接口, 使系統更加易用.

外觀模式正是體現迪米特法則, 客戶端只需要外觀類進行交互, 屏蔽了底層模塊.

下面是Apple被夷為平地和Dell破產的例子

UML

外觀模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        new TroubleFacade().boom();
    }
}

代理模式

此處僅介紹Java中的動態代理, 這里就直接看代碼

/**
 * @author Zhao Junjian
 */
public class MacBookProxy implements InvocationHandler {
    private Laptop target;

    public Laptop getProxy(MacBook macBook) {
        this.target = macBook;
        return (Laptop) Proxy.newProxyInstance(
                macBook.getClass().getClassLoader(),
                macBook.getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("dynamic proxy");
        return method.invoke(target, args);
    }
}

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final MacBook macBook = new MacBook();
        final Laptop proxy = new MacBookProxy().getProxy(macBook);
        // shutdown()是Laptop中的方法
        proxy.shutdown();
    }
}

作者:Chris
原博客:http://blog.chriscs.com

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容