原型模式(Prototype)

1.原型模式(Prototype)

原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。

所有的原型类都必须有一个通用的接口, 使得即使在对象所属的具体类未知的情况下也能复制对象。 原型对象可以生成自身的完整副本, 因为相同类的对象可以相互访问对方的私有成员变量。

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。通俗的讲就是当需要创建一个新的实例化对象时,我们刚好有一个实例化对象,但是已经存在的实例化对象又不能直接使用。这种情况下拷贝一个现有的实例化对象来用,可能会更方便。

以下情形可以考虑使用原型模式:

当new一个对象,非常繁琐复杂时,可以使用原型模式来进行复制一个对象。比如创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。

当需要new一个新的对象,这个对象和现有的对象区别不大,我们就可以直接复制一个已有的对象,然后稍加修改。

当需要一个对象副本时,比如需要提供对象的数据,同时又需要避免外部对数据对象进行修改,那就拷贝一个对象副本供外部使用。

using std::string;

// Prototype Design Pattern Intent: Lets you copy existing objects without making your code dependent on// their classes.

enum Type {

  PROTOTYPE_1 = 0,

  PROTOTYPE_2

};

/**

 * The example class that has cloning ability. We'll see how the values of field

 * with different types will be cloned.

 */

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;

  }

};

/**

 * ConcretePrototype1 is a Sub-Class of Prototype and implement the Clone Method

 * In this example all data members of Prototype Class are in the Stack. If you

 * have pointers in your properties for ex: String* name_ ,you will need to

 * implement the Copy-Constructor to make sure you have a deep copy from the

 * clone method

 */

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) {

  }

  /**

   * Notice that Clone method return a Pointer to a new ConcretePrototype1

   * replica. so, the client (who call the clone method) has the responsability

   * to free that memory. I you have smart pointer knowledge you may prefer to

   * use unique_pointer here.

   */

  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);

  }

};

/**

 * In PrototypeFactory you have two concrete prototypes, one for each concrete

 * prototype class, so each time you want to create a bullet , you can use the

 * existing ones and clone those.

 */

class PrototypeFactory {

 private:

  std::unordered_mapint>> prototypes_;

 public:

  PrototypeFactory() {

    prototypes_[Type::PROTOTYPE_1] = new ConcretePrototype1("PROTOTYPE_1 ", 50.f);

    prototypes_[Type::PROTOTYPE_2] = new ConcretePrototype2("PROTOTYPE_2 ", 60.f);

  }

  /**

   * Be carefull of free all memory allocated. Again, if you have smart pointers

   * knowelege will be better to use it here.

   */

  ~PrototypeFactory() {

    delete prototypes_[Type::PROTOTYPE_1];

    delete prototypes_[Type::PROTOTYPE_2];

  }

  /**

   * Notice here that you just need to specify the type of the prototype you

   * want and the method will create from the object with this type.

   */

  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;

}

2.原型模式优缺点

优点

缺点

你可以克隆对象, 而无需与它们所属的具体类相耦合。

 你可以用继承以外的方式来处理复杂对象的不同配置。

你可以克隆预生成原型, 避免反复运行初始化代码。

你可以更方便地生成复杂对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值