天天看點

原型模式--建立型模式

1、描述

原型是一種建立型設計模式,使你能夠複制對象,甚至是複雜對象,而又無需使代碼依賴它們所屬的類。所有的原型類都必須有一個通用的接口,使得即使在對象所屬的具體類未知的情況下也能複制對象。原型對象可以生成自身的完整副本,因為相同類的對象可以互相通路對方的私有成員變量。

2、結構圖

原型模式--建立型模式
  • 原型(Prototype)接口将對克隆方法進行聲明。在絕大多數情況下,其中隻會有一個名為clone的克隆方法
  • 具體原型(Concrete Prototype)類将實作克隆方法。除了将原始對象的資料複制到克隆體之外,該方法有時還需要處理克隆過程中的極端情況,例如克隆關聯對象和梳理遞歸依賴等等
  • 用戶端(Client)可以複制實作原型接口的任何對象

3、C++代碼

#include <string>
#include <vector>
#include <iostream>
#include <unordered_map>
using std::string;

enum Type {
  PROTOTYPE_1 = 0,
  PROTOTYPE_2
};


//具有克隆功能的測試類,我們将了解如何克隆具有不同類型的字段的值。
class Prototype {
 protected:
  string prototype_name_;
  float prototype_field_;

 public:
  Prototype() {}
  Prototype(string prototype_name)
      : prototype_name_(prototype_name) {
  }
  virtual ~Prototype() {}
  virtual Prototype *Clone() const = 0;
  virtual void Method(float prototype_field) {
    this->prototype_field_ = prototype_field;
    std::cout << "Call Method from " << prototype_name_ << " with field : " << prototype_field << std::endl;
  }
};

//具體原型,實作了Clone方法。該例子中所有的成員直接拷貝即可,如果你在實作中
//使用指針,需要實作拷貝構造函數確定實作深拷貝。
class ConcretePrototype1 : public Prototype {
 private:
  float concrete_prototype_field1_;

 public:
  ConcretePrototype1(string prototype_name, float concrete_prototype_field)
      : Prototype(prototype_name), concrete_prototype_field1_(concrete_prototype_field) {
  }

  //最好使用智能指針
  Prototype *Clone() const override {
    return new ConcretePrototype1(*this);
  }
};

class ConcretePrototype2 : public Prototype {
 private:
  float concrete_prototype_field2_;

 public:
  ConcretePrototype2(string prototype_name, float concrete_prototype_field)
      : Prototype(prototype_name), concrete_prototype_field2_(concrete_prototype_field) {
  }
  Prototype *Clone() const override {
    return new ConcretePrototype2(*this);
  }
};

//在原型工廠中有兩個具體的原型類,是以每次你想建立一個新的對象,可以使用現有的克隆出來
class PrototypeFactory {
 private:
  std::unordered_map<Type, Prototype *, std::hash<int>> prototypes_;

 public:
  PrototypeFactory() {
    prototypes_[Type::PROTOTYPE_1] = new ConcretePrototype1("PROTOTYPE_1 ", 50.f);
    prototypes_[Type::PROTOTYPE_2] = new ConcretePrototype2("PROTOTYPE_2 ", 60.f);
  }

  //最好使用智能指針
  ~PrototypeFactory() {
    delete prototypes_[Type::PROTOTYPE_1];
    delete prototypes_[Type::PROTOTYPE_2];
  }

  //注意這裡你隻需要指定原型的類型,該方法會建立一個這個類型的對象
  Prototype *CreatePrototype(Type type) {
    return prototypes_[type]->Clone();
  }
};

void Client(PrototypeFactory &prototype_factory) {
  std::cout << "Let's create a Prototype 1\n";

  Prototype *prototype = prototype_factory.CreatePrototype(Type::PROTOTYPE_1);
  prototype->Method(90);
  delete prototype;

  std::cout << "\n";

  std::cout << "Let's create a Prototype 2 \n";

  prototype = prototype_factory.CreatePrototype(Type::PROTOTYPE_2);
  prototype->Method(10);

  delete prototype;
}

int main() {
  PrototypeFactory *prototype_factory = new PrototypeFactory();
  Client(*prototype_factory);
  delete prototype_factory;

  return 0;
}
           

參考

https://refactoringguru.cn/