寫給自己看的設計模式之《外觀模式》

概念參考:https://blog.csdn.net/carson_ho/article/details/54910625
定義一個高層、統一的接口,通過這個接口實現外部對子系統多個接口的訪問

場景

  • 爲一個複雜的子系統對外提供一個簡單的接口
  • 提高子系統的獨立性
  • 客戶程序與多個子系統之間存在很大的依賴性,系統間解耦,挺高獨立性和可移植性
  • 在層次化結構中,可以使用外觀模式定義系統中每一層的入口

優點

  • 降低了客戶類與子系統類的耦合度
  • 外觀模式對客戶屏蔽了子系統組件,從而簡化了接口,減少了客戶處理的對象數目並使子系統的使用更加簡單
  • 降低原有系統的複雜度和系統中的編譯依賴性,並簡化了系統在不同平臺之間的移植過程

缺點

  • 在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的源代碼,違背了“開閉原則”
  • 不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性

使用

1. 定義子系統功能接口
/**
 * 功能接口
 *
 * @author dkangel
 */
public interface ISubsystem {
    /**
     * 打開
     */
    void turnOn();
    /**
     * 關閉
     */
    void turnOff();
}

2. 實現子系統
/**
 * 燈
 *
 * @author dkangel
 */
public class Light implements ISubsystem {
    @Override
    public void turnOn() {
        System.out.println("開燈");
    }

    @Override
    public void turnOff() {
        System.out.println("關燈");
    }
}
/**
 * 電視
 *
 * @author dkangel
 */
public class Television implements ISubsystem {
    @Override
    public void turnOn() {
        System.out.println("打開電視");
    }

    @Override
    public void turnOff() {
        System.out.println("關閉電視");
    }
}

3. 定義外觀類
/**
 * 外觀類
 *
 * @author dkangel
 */
public class Facade {
    private ISubsystem light;
    private ISubsystem tv;

    /**
     * 構造函數,實例化成員變量
     *
     * @param light 燈
     * @param tv    電視
     */
    public Facade(ISubsystem light, ISubsystem tv) {
        this.light = light;
        this.tv = tv;
    }

    /**
     * 打開操作
     */
    public void on() {
        light.turnOn();
        tv.turnOn();
    }

    /**
     * 關閉操作
     */
    public void off() {
        light.turnOff();
        tv.turnOff();
    }
}

4. 使用
/**
 * 外觀模式使用類
 *
 * @author dkangel
 */
public class Main {
    public static void main(String[] args) {
        ISubsystem light = new Light();
        ISubsystem tv = new Television();
        // 不使用外觀模式
        turnOnWithNoFacade(light, tv);
        turnOffWithNoFacade(light, tv);

        // 使用外觀模式,直觀看到使用了外觀模式後,客戶端調用更簡單,知道的東西更少
        Facade facade = new Facade(light, tv);
        turnOnWithFacade(facade);
        turnOffWithFacade(facade);
    }

    private static void turnOnWithNoFacade(ISubsystem light, ISubsystem tv) {
        light.turnOn();
        tv.turnOn();
    }

    private static void turnOffWithNoFacade(ISubsystem light, ISubsystem tv) {
        light.turnOff();
        tv.turnOff();
    }

    private static void turnOnWithFacade(Facade facade) {
        facade.on();
    }

    private static void turnOffWithFacade(Facade facade) {
        facade.off();
    }
}

與適配器模式的區別

  • 外觀模式的實現核心主要是——由外觀類去保存各個子系統的引用,實現由一個統一的外觀類去包裝多個子系統類,然而客戶端只需要引用這個外觀類,然後由外觀類來調用各個子系統中的方法
  • 適配器模式是將一個對象包裝起來以改變其接口,而外觀是將一羣對象 ”包裝“起來以簡化其接口。它們的意圖是不一樣的,適配器是將接口轉換爲不同接口,而外觀模式是提供一個統一的接口來簡化接口
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章