iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
Software Development

輕鬆學習設計模式Design Pattern系列 第 22

Day 22 原型模式 Prototype Pattern

  • 分享至 

  • xImage
  •  

想像一下你手上有一個心愛的玩偶,這個玩偶有著獨特的外觀、材質和手感。如果你想要再擁有一個一模一樣的玩偶,你會怎麼做呢?重新製作一個可能需要花費很多時間與精力,但如果有一個神奇的「複製器」,只要按一下按鈕,就能夠完美複製出另一個相同的玩偶,那該有多方便!這就是「原型模式(Prototype Pattern)」在軟體設計中的核心思想。這種模式讓我們能夠快速複製已經存在的物件,而不需要從頭再建立一遍。

什麼是原型模式?

原型模式是一種建立型設計模式,它允許我們透過複製現有的物件來建立新物件,而不是透過傳統的方式來構建新物件。這種方式特別適合於物件建立成本高昂或結構複雜的情境。具體來說原型模式包含了一個介面,這個介面定義了複製自身的能力。每個實現這個介面的物件都能夠建立一個自己的複本,並且複製出來的新物件與原始物件在狀態上是相同的。

在C++中,這通常是透過深拷貝或淺拷貝來實現的。深拷貝會複製物件中的所有資料,包括內部指標所指向的資源,而淺拷貝則只複製物件的基本結構,而共享內部資源。

想像你正在開發一個角色扮演遊戲。遊戲中有各種各樣的怪物,每種怪物都有自己的屬性和技能。如果每次需要新怪物時都要從頭建立,傳入很多參數跟設定數值,那將是一個繁瑣的過程。這時原型模式就能派上用場了。

再舉個例子,想像你正在開發一個圖形設計軟體,其中有些常用的圖形,例如矩形,客戶端在使用時可能需要頻繁地建立相似的矩形,而這些矩形的基本屬性是相同的(顏色、寬度、高度),為了提高客戶端的工作效率,就能夠使用原型模式快速複製產生新的矩形物件。

這個模式的基本角色包括:

  1. 原型(Prototype):宣告一個複製自己本身的介面。
  2. 具體原型(Concrete Prototype):實現複製自己本身的方法。
  3. 客戶端(Client):透過呼叫原型的複製方法來取得新的物件。

原型模式在遊戲角色建立中的應用

讓我們以遊戲開發為例,來看看原型模式的應用。一個典型的角色扮演遊戲(RPG)中,玩家可以選擇不同的職業,每個職業都有其獨特的屬性、技能和裝備。如果每次建立一個新角色都要從頭設定這些屬性,那將是非常耗時的事情。但如果我們能夠建立一個基礎角色的原型,然後透過複製這個原型來產生新角色,就能夠大大簡化這個過程。

首先我們定義一個 Prototype 介面,它包含了一個 clone() 方法,這個方法用來複製物件,

// 原型 Prototype
class CharacterPrototype {
public:
    virtual CharacterPrototype* clone() const = 0;
    virtual void showAttributes() const = 0;
    virtual ~CharacterPrototype() = default;
};

接著我們建立一個具體的角色類別,例如一個戰士角色,

// 具體原型 Concrete Prototype
class Warrior : public CharacterPrototype {
private:
    int strength;
    int defense;
    std::string weapon;

public:
    Warrior(int str, int def, const std::string& weap)
        : strength(str), defense(def), weapon(weap) {}

    CharacterPrototype* clone() const override {
        return new Warrior(*this);
    }

    void showAttributes() const override {
        std::cout << "Warrior with strength: " << strength
                  << ", defense: " << defense
                  << ", weapon: " << weapon << std::endl;
    }
};

現在我們在客戶端可以使用這個角色原型來建立新角色,

int main() {
    // 建立初始角色
    CharacterPrototype* originalWarrior = new Warrior(100, 50, "Sword");

    // 複製角色
    CharacterPrototype* clonedWarrior = originalWarrior->clone();

    originalWarrior->showAttributes();  // 輸出:Warrior with strength: 100, defense: 50, weapon: Sword
    clonedWarrior->showAttributes();    // 輸出:Warrior with strength: 100, defense: 50, weapon: Sword

    delete originalWarrior;
    delete clonedWarrior;

    return 0;
}

執行上述程式碼,我們會得到以下輸出:

Warrior with strength: 100, defense: 50, weapon: Sword
Warrior with strength: 100, defense: 50, weapon: Sword

在這個例子中,我們建立了一個戰士角色作為原型,並使用原型的 clone() 方法產生了一個一模一樣的新角色。這樣,我們不需要每次建立新角色時都手動設定屬性,而是透過簡單的複製操作快速產生所需的角色。

原型模式的優缺點

原型模式的一大優點是它提供了一種高效的物件建立方式,特別是在需要多次建立類似物件的情況下,能夠節省大量時間和資源。由於原型模式直接複製現有的物件,我們可以保證新物件與原始物件具有相同的狀態,這在某些需要精確控制物件狀態的場景中尤為重要。

然而原型模式的缺點在於複製過程的複雜性。當物件的結構非常複雜或包含指標、動態分配的資源時,正確地實現深拷貝可能會變得困難。這要求開發者對物件的內部結構有非常清晰的理解,並且小心處理拷貝過程中的細節。另外如果物件中包含了不應該被複製的部分,或需要在複製後進行一些特定處理,那麼在實際應用中可能會遇到額外的挑戰。

整理來說原型模式在適合的情境下能夠極大地提高開發效率,但也需要謹慎使用,確保在複製物件時沒有引入額外的複雜度或潛在的錯誤。

總結

原型模式在我們的日常生活中也隨處可見,影印機複印文件時,原始文件就是原型,複印出來的每一份都是複製品。在細胞分裂中,新的細胞是從原有細胞複製而來的。這些例子都體現了原型模式的核心思想:透過複製現有的物件來建立新物件。

原型模式是一種強大而靈活的建立型設計模式,適合於那些需要複製大量相似物件的應用場景。透過原型模式,我們可以輕鬆地產生具有相同屬性和狀態的新物件,從而提高開發效率,降低複雜度。然而在使用時需要注意物件複製過程中的潛在風險,特別是涉及到深拷貝和資源管理時。

設計模式是解決問題的工具,而不是目的本身。靈活運用才能寫出既優雅又實用的程式碼。在軟體開發的道路上,讓我們能像原型模式一樣,在「複製」中不斷成長,創造出屬於自己的精彩作品。

更多C++語言相關的文章,歡迎追蹤我的部落格。
https://shengyu7697.github.io/cpp-prototype-pattern/


上一篇
Day 21 享元模式 Flyweight Pattern
下一篇
Day 23 訪問者模式 Visitor Pattern
系列文
輕鬆學習設計模式Design Pattern30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言