iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0
Software Development

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

[Day 05] 烘焙物件的精華 - 工廠模式 (Factory Pattern)

  • 分享至 

  • xImage
  •  

工廠模式 (Factory Pattern)

In Factory pattern, we create object without exposing the creation logic to the client and refer to newly created object using a common interface

  • 關鍵字
    • 看到 "new" 就要想到 "具體"
      • 如果你讓程式使用太多具體類別,那就等於自找麻煩 (每當有新的具體類別加入,就要修改那段程式)
    • 依賴反轉原則
      • 要依賴抽象,不要依賴具體類別
    • 將 Creator 與 Product 視為平行的

經典範例1 (非書本): UML Diagram for Simple Factory Pattern

https://ithelp.ithome.com.tw/upload/images/20230917/20138643VRtVD2C15z.png

// 定義一個銀行帳戶的基礎接口
class BankAccount {
public:
    virtual ~BankAccount() {}

    virtual void validateUserIdentity() = 0;
    virtual void calculateInterestRate() = 0;
    virtual void registerAccount() = 0;
};

// 三種具體的銀行帳戶類型
class PersonalAccount : public BankAccount {
    // 具體方法的實現可以根據需要填寫
    void validateUserIdentity() override {}
    void calculateInterestRate() override {}
    void registerAccount() override {}
};

class BusinessAccount : public BankAccount {
    void validateUserIdentity() override {}
    void calculateInterestRate() override {}
    void registerAccount() override {}
};

class CheckingAccount : public BankAccount {
    void validateUserIdentity() override {}
    void calculateInterestRate() override {}
    void registerAccount() override {}
};

// 銀行帳戶工廠類
class BankAccountFactory {
public:
    // 根據帳戶類型創建相應的帳戶對象
    BankAccount* createAccount(const std::string& type) {
        BankAccount* bankAccount = nullptr;
        if (type == "P") {
            bankAccount = new PersonalAccount();
        } else if (type == "B") {
            bankAccount = new BusinessAccount();
        } else if (type == "C") {
            bankAccount = new CheckingAccount();
        } else {
            std::cout << "Invalid type" << std::endl;
        }
        return bankAccount;
    }
};

// 銀行分行類
class Branch {
private:
    BankAccountFactory* bankAccountFactory;

public:
    Branch(BankAccountFactory* factory) : bankAccountFactory(factory) {}

    // 根據賬戶類型開設新賬戶
    BankAccount* openAccount(const std::string& type) {
        BankAccount* bankAccount = bankAccountFactory->createAccount(type);
        bankAccount->validateUserIdentity();
        bankAccount->calculateInterestRate();
        bankAccount->registerAccount();

        return bankAccount;
    }
};
  • 在這個例子中,Factory Class 提供了一個 createAccount 方法,這個方法根據傳入的參數 type 來決定創建哪種 Account。主程式不需要知道具體的 Account Type,只需要知道 Factory Class 和 Account 的 Interface,這樣可以很容易地添加新的 Account Type,而不需要修改主程式
  • 但我們還可以再改進這個簡單工廠模式,以便完全封裝對象生成 (fully encapsulated the object generation)

經典範例2 (非書本): UML Diagram for Factory Pattern

https://ithelp.ithome.com.tw/upload/images/20230917/20138643fdvFnQwv9c.png

class Branch {
private:
    std::unique_ptr<BankAccountFactory> bankAccountFactory;
public:
    Branch(std::unique_ptr<BankAccountFactory> factory) : bankAccountFactory(std::move(factory)) {}

    BankAccount* createBankAccount(const std::string& type) {
        return bankAccountFactory->createAccount(type);
    }
};

int main() {

    std::unique_ptr<BankAccount> bankAccount;

    std::cout << "Please enter" << std::endl
              << " P for Personal account" << std::endl
              << " B for Business account" << std::endl
              << " C for Checking account" << std::endl
              << "----------------------------" << std::endl;

    std::string type;
    std::getline(std::cin, type);

    std::cout << "Please enter" << std::endl
              << " 1 for Local" << std::endl
              << " 2 for Foreign" << std::endl
              << "----------------------------" << std::endl;

    int branch;
    std::cin >> branch;

    // 這邊再度改進了前一個範例的工廠模式,現在可以針對不同分行做出更彈性的 createBankAccount
    if (branch == 1) {
        Branch localBranch(std::make_unique<LocalBankAccountFactory>());
        bankAccount.reset(localBranch.createBankAccount(type));
    } else if (branch == 2) {
        Branch foreignBranch(std::make_unique<ForeignBankAccountFactory>());
        bankAccount.reset(foreignBranch.createBankAccount(type));
    }

    return 0;
}

Reference

[1]. https://www.tutorialspoint.com/design_pattern/factory_pattern.htm
[2]. https://prasadct.medium.com/factory-method-design-patternfactory-method-design-pattern-with-real-world-example-4ee909a24ab6


上一篇
[Day 04] 為愛用繼承的人設計一對眼睛 - 裝飾器模式 (Decorator Pattern)
下一篇
[Day 06] 讓工廠再解藕 - 抽象工廠模式 (Abstract Factory Pattern)
系列文
深入淺出設計模式 - 使用 C++37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言