• 原型模式(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()
  • 相关阅读:
    上传图片到FTP的实例
    关于浏览器兼容问题:获取div的值
    多张表数据导入到execl中
    把泛型转换成dataTable
    关于游标
    Excel 公式 两个时间比大小
    SQL 执行顺序
    VBA实现随意输入组合码,查询唯一标识码
    IIS7 503错误 Service Unavailable
    汇总文件数据 VBA
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11821205.html
Copyright © 2020-2023  润新知