• 原型模式(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()
  • 相关阅读:
    C# TcpServer调试工具
    C#调用百度AI开发平台
    MVC 身份证图像识别(调用dll)
    12.智能快递柜(其他功能)
    智能信报箱
    北斗卫星短信平台
    11.智能快递柜(用户寄件)
    WindowServer优化
    13.智能快递柜(对接流程)
    sublime text3 手动安装插件package control
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11821205.html
Copyright © 2020-2023  润新知