動機
在軟件系統中,經常面臨著某些結構復雜的對象的創建工作;由于需求的變化,這些對象經常面臨著劇烈的變化,但是它們卻擁有比較穩定一致的接口。
之前的工廠方法和抽象工廠將抽象基類和具體的實現分開。原型模式也差不多,但是原型模式將抽象基類合并。
原型模式的應用場景
原型模式特別適用于以下場景:
- 對象的創建過程比較復雜或耗時。
- 需要動態創建對象,且對象的類型在運行時才能確定。
- 需要避免重復初始化對象的開銷。
#include <iostream>
#include <memory>
#include <string>// 抽象類
class ISplitter {
public:virtual void split() = 0;virtual std::unique_ptr<ISplitter> clone() const = 0; // 返回一個智能指針virtual ~ISplitter() {}
};// 二進制拆分器
class BinarySplitter : public ISplitter {
private:std::string data; // 假設這是需要拆分的二進制數據
public:BinarySplitter(const std::string& data) : data(data) {}void split() override {std::cout << "Splitting binary data: " << data << std::endl;// 具體的二進制拆分邏輯}std::unique_ptr<ISplitter> clone() const override {return std::make_unique<BinarySplitter>(*this); // 深拷貝}
};// 文本拆分器
class TxtSplitter : public ISplitter {
private:std::string data; // 假設這是需要拆分的文本數據
public:TxtSplitter(const std::string& data) : data(data) {}void split() override {std::cout << "Splitting text data: " << data << std::endl;// 具體的文本拆分邏輯}std::unique_ptr<ISplitter> clone() const override {return std::make_unique<TxtSplitter>(*this); // 深拷貝}
};// 使用示例
int main() {// 創建原始對象BinarySplitter binarySplitter("01010101");TxtSplitter txtSplitter("Hello, World!");// 克隆對象std::unique_ptr<ISplitter> binaryClone = binarySplitter.clone();std::unique_ptr<ISplitter> txtClone = txtSplitter.clone();// 使用克隆對象binaryClone->split();txtClone->split();return 0;
}
模式定義
使用原型實例指定創建對象的種類,然后通過拷貝這些原型來創建新的對象。
什么時候使用原型,什么時候使用工廠最大的區分點就在于:用工廠方法創建對象是不是非常簡單的幾個步驟就可以把這個對象創建出來,還是說需要考慮對象很復雜的中間狀態,然后又很希望保留這個中間狀態,如果是后者的話就用原型。
要點總結
Prototype模式同樣用于隔離類對象的使用者和具體類型(易變類)之間的耦合關系,它同樣要求這些“易變類”擁有穩定的接口。
Prototype模式對于“如何創建易變類”的實體對象“采用”原型克隆的方法來做,它使得我們可以非常靈活地動態創建“擁有某些穩定接口”的新對象–所需工作僅僅是注冊一個新類的對象(即原型),然后在任何需要的地方Clone。
Prototype模式中的Clone方法可以利用某些框架中的序列化來實現深拷貝。