原型模式(prototype)

1、作用

原型模式可以用指向基类的子类指针指针或者引用,拷贝出子类对象。拷贝构造函数只能用子类的对象拷贝构造子类对象。使用原型模式的目的是实现多态,根据指针指向的类型实现动态拷贝。

2、实现方式

原型模式的重点是在基类中定义了一个clone的虚函数,在子类中重写clone函数,且每个clone函数调用当前类的拷贝构造函数,这样就能实现动态拷贝,即指向基类的子类指针通过调用clone函数,能够拷贝子类的数据域。

3、C++代码

Animal.h

#include <string>
#include <iostream>

#ifndef ANIMAL__H
#define ANIMAL__H

class Animal {
    public:
        Animal() = default;
        Animal(const std::string &n):name(n) {std::cout<<"Animal()"<<std::endl; }
        Animal(const Animal &a) :name(a.name) {std::cout<<"Animal(Animal &a)"<<std::endl;}
        virtual Animal *clone(); 
        virtual ~Animal() { std::cout<<"~Animal()"<<std::endl; }
        virtual std::string &getName() {return name;}
    protected:
        std::string name;
};

#endif

Animal.cc

#include "Animal.h"

Animal *Animal::clone() {
    std::cout<<"Animal::clone()"<<std::endl;
    return new Animal(*this);
}

Rabbit.h

#include "Animal.h"
#include <iostream>
#include <vector>
#include <string>

#ifndef RABBIT__H
#define RABBIT__H

class Rabbit:public Animal {
    public:
        Rabbit(const std::string &n); 
        Rabbit(Rabbit &r); 
        ~Rabbit();
        void addFood(const std::string &f) { food->push_back(f); }
        std::vector<std::string> *getFood() { return food; }
        virtual Animal *clone() override;
    private:
        std::vector<std::string> *food = nullptr;
};

#endif

Rabbit.cc

#include "Rabbit.h"

Rabbit::Rabbit(const std::string &n): Animal(n) , food(new std::vector<std::string>){
    std::cout<<"Rabbit()"<<std::endl;
}

Rabbit::Rabbit(Rabbit &r):Animal(r), food(new std::vector<std::string>){
    for(const auto &v : *(r.food))
        food->push_back(v);
    std::cout<<"Rabbit(&Rabbit)"<<std::endl;
}


Animal *Rabbit::clone() {
    std::cout<<"clone()"<<std::endl;
    return new Rabbit(*this);
}

Rabbit::~Rabbit() {
    std::cout<<"~Rabbit()"<<std::endl;
    delete food;
}

test.cc

#include <iostream>
#include "Rabbit.h"
#include <iomanip>

using namespace std;

int main() {
    Rabbit r("hehe");
    r.addFood("cabbage");
    Rabbit r1(r);
    r1.addFood("radish");

    Animal *a = &r1;
    Animal *b = a->clone();
    std::cout<<"---------------------"<<endl;
    std::cout<<"name:"<<b->getName()<<endl;
    std::cout<<"foods:"<<endl;
    for(const auto &v : *(static_cast<Rabbit*>(b)->getFood())) {
        std::cout<<right<<setw(12)<<v<<endl;
    }
    std::cout<<"---------------------"<<endl
}

输出:

Animal()
Rabbit()
Animal(Animal &a)
Rabbit(&Rabbit)
clone()
Animal(Animal &a)
Rabbit(&Rabbit)
---------------------
name:hehe
foods:
     cabbage
      radish
---------------------
~Rabbit()
~Animal()
~Rabbit()
~Animal()
原文地址:https://www.cnblogs.com/yuandonghua/p/11821205.html