iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0
Software Development

深入淺出設計模式 - 使用 C++系列 第 12

[Day 12] 回顧比較 — Decorator / Adapter / Facade 三種 Design Patterns

  • 分享至 

  • xImage
  •  

目的比較

敘述 目的
Adapter 將一個類別的介面轉換為另一個介面 使原本由於介面不相容而不能一起工作的兩個類別可以一起工作
Decorator 向一個物件添加新的功能 通過創建一個包含目標物件的類,並重寫目標物件的方法來實現
Facade 為子系統中的一組接口提供一個統一的高層接口 使得子系統更容易使用,通常用於簡化一組繁複接口或者隱藏子系統的內部細節從而提供一個簡化介面到客戶端

相同之處

  • All of them are defined as structural patterns as GOF design pattern
  • All of them uses Composition and delegation to fulfill there intent
    • Adapter uses composition to forward calls from target interface to adaptee interface
    • Decorator also uses same technique before adding new behavior
    • Facade is composed of all sub components
  • Both Adapter and Facade pattern, forwards requests to a different interface, which can be either adaptee or any component interface from sub-system

相異之處

  • Unlike Decorator, Facade doesn't add any new behavior, it just call existing methods from interface
  • Adapter pattern converts interface, Decorator & Facade patterns don't
  • Decorator just implements original object's interface, so that it can be passed to a method, which accepts an original object

UML Diagram of 3 Patterns

  1. Adapter pattern
    https://ithelp.ithome.com.tw/upload/images/20230924/20138643sAu6MkkAGA.png
  2. Decorator pattern
    https://ithelp.ithome.com.tw/upload/images/20230924/20138643RTr4LV1pIg.png
  3. Facade pattern
    https://ithelp.ithome.com.tw/upload/images/20230924/20138643ISPNAKRWOn.png

[補充]: 組合 (Composition) vs 委派 (Delegation)

組合:

  • 用於建立一個新類別,該類別包含一或多個現有類別的實例作為其成員變量。組合可以實現「有一個」(Has-a)的關係
    • 建立對象: 在新類別中建立一個或多個現有類別的實例
    • 方法封裝: 新類別可以封裝或者擴展被包含對象的功能
    • 附加功能: 根據需要,新類別可以添加額外的方法和屬性
  • 範例
// "Engine" 類別
class Engine {
public:
    void start() {
        std::cout << "Engine started" << std::endl;
    }
};

// "Car" 類別包含 "Engine"
class Car {
private:
    Engine engine;
public:
    Car() : engine() {}
    void start() {
        engine.start();
    }
};

int main() {
    Car car;
    car.start();
}

委派:

  • 是一種將某個操作的責任轉交給另一個對象的技巧。這通常用於實現代碼重用和靈活性
    • 建立接口: 為需要委派的功能建立一個接口
    • 實現接口: 被委派類別會實現這個接口
    • 轉交責任: 在主類別中,建立被委派類別的一個實例,並將該實例用作執行特定任務
  • 範例
// "Printer" 介面
class Printer {
public:
    virtual void print_page(const string& content) = 0;
};

// "InkjetPrinter" 實現 "Printer"
class InkjetPrinter : public Printer {
public:
    void print_page(const string& content) override {
        cout << "Printing from Inkjet: " << content << endl;
    }
};

// "LaserPrinter" 實現 "Printer"
class LaserPrinter : public Printer {
public:
    void print_page(const string& content) override {
        cout << "Printing from Laser: " << content << endl;
    }
};

// "Document" 使用委派
class Document {
private:
    Printer* printer;
public:
    Document(Printer* p) : printer(p) {}
    
    void print(const string& content) {
        printer->print_page(content);
    }
};

int main() {
    InkjetPrinter inkjet;
    LaserPrinter laser;
    Document doc1(&inkjet);
    Document doc2(&laser);
    doc1.print("Hello, world!");
    doc2.print("Hello, world!");
    
    // 輸出為:
    // Printing from Inkjet: Hello, world!
    // Printing from Laser: Hello, world!
}
  • 小結
    • 組合: 適用於「Has-a」關係,並希望直接使用或擴展被包含對象的功能
    • 委派: 適用於需要代碼重用,或在運行時能動態更改行為

Reference

  1. https://ahmedabdelkarim.wordpress.com/2019/11/21/facade-vs-adapter-vs-decorator-design-pattern/
  2. https://javarevisited.blogspot.com/2015/01/adapter-vs-decorator-vs-facade-vs-proxy-pattern-java.html#axzz8EEMvOEuO

上一篇
[Day 11] 讓介面更簡單 – 門面模式 (Facade Pattern)
下一篇
[Day 13] 封裝演算法元素 - 樣板方法模式 (Template Method Pattern)
系列文
深入淺出設計模式 - 使用 C++37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言