创建型 原型模式

简介: 创建型 原型模式

原型模式(Prototype Pattern): 创建重复的对象,同时又能保证性能,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

原型模型

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象

分析实现:

通过对象的拷贝,构造相同类型的对象。例如:试卷的复印

给类提供一个接口,实现对象的复制,这里注意类内成员的深拷贝和浅拷贝。

使用场景:

1:对象类型一开始不确定,运行中确定,可以克隆创建

2:需要使用对象的副本

3:创建对象时,过多的构造和析构,可以用原型模式

源码demo:

#include <iostream>
#include <string.h>
using namespace std;
class Person
{//抽象类提供接口
public:
  virtual Person *Clone() const = 0;//返回基类指针
  virtual void printT() const = 0;
  virtual ~Person() {}
};
class JavaProgrammer : public Person
{
private:
  string  m_name;
  int   m_age;
  char    *m_resume;
public:
  JavaProgrammer()//无参构造函数
  {
    this->m_name = "";
    this->m_age = 0;
    m_resume = NULL;
  }
  JavaProgrammer(string name, int age)//有参构造函数
  {
    this->m_name = name;
    this->m_age = age;
    m_resume = NULL;
  }
  ~JavaProgrammer()
  {
    if (m_resume != NULL)
    {
      free(m_resume);
      m_resume = NULL;
    }
  }
  //实现自我复制功能 这里应该调用拷贝构造函数  但是涉及深拷贝与浅拷贝问题,这里直接做内存的处理
  Person *Clone() const override
  {
    JavaProgrammer *p = new JavaProgrammer();
    p->m_resume = new char[strlen(this->m_resume) + 1];
    p->m_name = this->m_name;
    strcpy(p->m_resume, this->m_resume);
        // return new JavaProgrammer(*this); 浅拷贝 这里成员在析构中释放,会报错
    return p;
  }
  void setResume(const char *resume)
  {
    m_resume = new char[strlen(resume) + 1]; //因为是字符串末尾多一个'\0'
    strcpy(m_resume, resume);
  }
  void printT() const override
  {
    cout << "m_name:" <<  m_name << "\t" << "m_age:" << m_age << endl;
    if (m_resume != NULL)
    {
      cout << m_resume << endl;
    }
  }
};
int main()
{
  JavaProgrammer javaperson1("李四", 160);
  javaperson1.setResume("我是C++程序员");//字符串操作,使用函数完成初始化操作。注意字符串操作的时候要进行'\0''
  //如果不使用这个函数进行封装,那么就会出现深拷贝和浅拷贝的问题  
  //如果没有这个函数,那么在指针自我拷贝的时候吗,我们就要把内存给创建出来,然后在去进行赋值操作
  javaperson1.printT();//自己打印自己的信息
  Person *p2 = javaperson1.Clone();  //对象具有自我复制功能 注意深拷贝和浅拷贝问题
  p2->printT();
  if(p2 != NULL)
  {
    delete p2;
    p2 = NULL;
  }
  return 0;
}

百度到一个好的代码: https://refactoringguru.cn/design-patterns/cpp

// 代码来自 https://refactoringguru.cn/design-patterns/cpp
#include <iostream>
#include <string.h>
#include <map>
#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;
    }
};
//子类实现不同的原型构造 浅拷贝拷贝构造   需要客户自己释放
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;
}
目录
相关文章
|
5月前
|
Java 数据库
原型模式
原型模式
35 1
|
设计模式
2023-6-14-第五式原型模式
2023-6-14-第五式原型模式
69 0
|
设计模式 Java 关系型数据库
原型模式解读
原型模式解读
|
安全 Java
创建型模式-原型模式
创建型模式-原型模式
119 0
|
设计模式
大话总结——创建型
大话总结——创建型
77 0
大话总结——创建型
原型模式必知必会
原型模式必知必会
106 0
原型模式必知必会
|
设计模式 JSON JavaScript
我学会了,原型模式
原型模式属于创建型模式,这个类型的设计模式是将 对象的创建和使用解耦了,花式的去创建对象。
148 0
我学会了,原型模式
|
Java 测试技术 API
原型模式 与 建造者模式(2)
原型模式 与 建造者模式(2)
132 0
原型模式 与 建造者模式(2)
|
JSON Java uml
原型模式 与 建造者模式(1)
原型模式 与 建造者模式(1)
213 0
原型模式 与 建造者模式(1)
|
Java
原型模式 与 建造者模式(3)
原型模式 与 建造者模式(3)
140 0
原型模式 与 建造者模式(3)