原型模式详解与应用场景

## 原型模式原理

原型模式相关原理可以参考菜鸟学院链接。其实大致原理说起来也很简单,就是不使用构造函数,而是采用clone接口进行对象的创建和原对象的复制,是一个设计模式中的一个创建型模式,而本篇博文主要讲述的是,大多数博文中都没有讲清楚的,为何不使用构造函数,而是使用clone接口函数进行原对象的创建和复制,原型模式的应用场景是什么。
我们来看:大多数博文中,所说,
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。(构造函数不可以创建对象吗?构造后再赋值不就可以吗?)
主要解决:在运行期建立和删除原型;(构造函数不可以在运行期间使用吗?)
优点: 1、性能提高。 2、逃避构造函数的约束。(构造函数是犯了什么错,我们要嫌弃他?)
如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例。(这才是重点,快速生成原型对象)
那我来总结一下:本篇博文,最终要证明的一个观点。
原型模式主要解决的是,当构造函数需要大规模初始化资源情况下,原型模式可以定制化,将我们需要的修改的资源深拷贝,后续可以和原对象资源分离,修改后不会影响原对象,而不需要修改的资源直接浅拷贝即可,让他们指向相同的引用,那么我们相较于构造函数,不用修改的部分资源可以得以节省,即可快速创建一个相较于原对象定制化的对象。
话不多说,我们代码来解释。
代码设计:
孙悟空 分身 简单粗暴
属性:
1.姓名;
2.性别;
3.衣着;
4.攻击力;
5.分身后身份;
第一种分身:猪八戒
第二种分身:孙大娘
第三种分身:猴子猴孙
第四种分身:假猴

person.h
#pragma once
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
/*人物接口*/
typedef enum{
    MAN = 0,
    WOMAN
}GENDER;

class person
{
    public:
        char *name;  //姓名
        char gender;  //性别:0->男 1->女
        char *dressd; //衣着
        int attack;  //攻击力
        char *pretendName; //伪装后身份
    public:
        ~person()
        {
            if(name != nullptr)
                delete name;
            if(dressd != nullptr)
                delete dressd;
            if(pretendName != nullptr)
                delete pretendName;
            name = dressd = pretendName =nullptr;
        }
        person() = delete;
        person(const char *name)
        {
            setPretendName("没有伪装");
            int nameLen = strlen(name);
            this->name = new char[nameLen+1];
            strncpy(this->name,name,nameLen);
        }
        void setName(const char *name)
        {
            if(this->name != nullptr)
            {
                delete this->name;
            }
            int nameLen = strlen(name);
            this->name = new char[nameLen+1];
            strncpy(this->name,name,nameLen);
        }
        char* getName()
        {
            return name;
        }
        bool setGender(int gender)
        {
            if(gender <  0 || gender > 1)
            {
                return false;
            }
            this->gender = gender;
            return true;
        }
        const char *getGender() const
        {
            switch (gender)
            {
            case 0:
                return "男";
            case 1:
                return "女";
            default:
                return "未知性别";
            };
        }
        bool setDressd(const char *dress)
        {
            if(this->dressd != nullptr)
            {
                delete this->dressd;
            }
            int dressLen = strlen(dress);
            this->dressd = new char[dressLen + 1];
            strncpy(this->dressd , dress , dressLen);
            return true;
        }
        const char* getDress() const
        {
            return dressd;
        }
        void setAttack(int attack)
        {
            this->attack = attack;
        }
        int getAttack()
        {
            return attack;
        }
        bool setPretendName(const char* name)
        {
            if(this->pretendName != nullptr)
            {
                delete this->pretendName;
            }
            int nameLen = strlen(name);
            this->pretendName = new char[nameLen + 1];
            strncpy(this->pretendName , name , nameLen);
            *(this->pretendName+nameLen) = '\0';
            return true;
        }
        const char *getPretendName() const
        {
            return pretendName;
        }
};
ostream& operator << (ostream& outp , person& c)
{
    outp<<"姓名:"<<c.getName()<<endl;
    outp<<"性别:"<<c.getGender()<<endl;
    outp<<"衣着:"<<c.getDress()<<endl;
    outp<<"攻击力:" <<c.getAttack()<<endl;
    outp<<"伪装:"<<c.getPretendName()<<endl;
    cout<<"***************************"<<endl<<endl;;
    return outp;
}
#pragma once
#include <typeinfo>
#include "prototype.h"
#include "person.h"
class sunwukong : public Prototype , public person
{
    public:
        sunwukong():person("孙悟空")
        {
            setGender(MAN);
            setAttack(100000);
            setDressd("锁子黄金甲,凤翅紫金冠,藕丝步云履,如意金箍棒");
        }
        Prototype* Clone(person *soucePerson)
        {
            cout<<typeid(*soucePerson).name()<<endl;                //本来准备使用typeid区分不同的子类 但是这里区分全部都是父类 不明原因。。。
            return personCreate(soucePerson);                        //欢迎指导
        }
        sunwukong *personCreate(person *sourcePerson)
        {
            sunwukong * backPerson = nullptr;
            if(0 != strcmp(sourcePerson->getName() , "孙悟空"))     //孙大娘 猪八戒 猴子猴孙   因为其他都需要改变所以全部采用深拷贝方式进行
            {
                backPerson = new sunwukong(sourcePerson);
                backPerson->name= this->name;
                backPerson->setAttack(sourcePerson->getAttack());
                backPerson->setDressd(sourcePerson->getDress());
                if(0 == strcmp(sourcePerson->getGender(),"男"))
                    backPerson->setGender(MAN);
                else
                     backPerson->setGender(WOMAN);
                backPerson->setPretendName(sourcePerson->getName());
            }
            else if(0 == strcmp(sourcePerson->getName() , "孙悟空"))            //真假悟空穿着姓名都引用悟空的
            {
                backPerson = new sunwukong(sourcePerson);
                backPerson->setPretendName("假悟空");
                backPerson->setAttack(0);
                backPerson->name = const_cast<char *>(sourcePerson->getName());
                backPerson->dressd = const_cast<char *>(sourcePerson->getDress());
                backPerson->setGender(MAN);
            }
            else
            {
                return nullptr;
            }
            return backPerson;
        }
        private:
            sunwukong(person *sourceType):person("孙悟空"){};
};
prototype.h
#pragma once
#include "person.h"
class Prototype // Prototype(抽象原型角色):是抽象类或者接口,用来声明clone方法。该方法是用来克隆自身的接口。
{
public:
	virtual ~Prototype() = default;
	virtual Prototype* Clone(person *soucePerson)  = 0;
};
houzihousun.h
#pragma once
#include "person.h"
class houzihousun: public person
{
    public:
        houzihousun():person("猴子猴孙")
        {
            setGender(MAN);
            setAttack(18);
            setDressd("一张桃子形的面孔上,嵌着两颗闪着金光的眼睛,整天骨碌骨碌地直转,好像在打着什么主意.那小小的鼻子又塌又扁,而鼻孔却很大.鼻子下面有一张尖尖的大嘴巴,可爱极了!");
        }
};
sundaniang.h
#pragma once
#include "person.h"
class sundaniang: public person
{
    public:
        sundaniang():person("孙大娘")
        {
            setGender(WOMAN);
            setAttack(23);
            setDressd("露出绿纱衫儿来,头上黄烘烘的插着一头钗环,鬓边插着些野花");
        }
};
zhubajie.h
#pragma once
#include "person.h"
class zhubajie: public person
{
    public:
        zhubajie():person("猪八戒")
        {
            setGender(MAN);
            setAttack(60);
            setDressd("黑脸短毛,长喙大耳,穿一身青不青,蓝不蓝的梭布直裰,系一条花布手巾");
        }
};
main.cpp
#include <iostream>
#include "prototype.h"
#include "sundaniang.h"
#include "zhubajie.h"
#include "houzihousun.h"


int main(void)
{
    sunwukong *p = new sunwukong();
    sunwukong *p_sundaniang = (sunwukong *)(p->Clone(new sundaniang()));
    sunwukong *p_houzihousun = (sunwukong *)(p->Clone(new houzihousun()));
    sunwukong *p_zhubajie = (sunwukong *)(p->Clone(new zhubajie()));
    sunwukong *p_sunwukong = (sunwukong *)(p->Clone(p));
    cout<<*p_sundaniang<<endl;
    cout<<*p_houzihousun<<endl;
    cout<<*p<<endl;
    cout<<*p_zhubajie<<endl;
    cout<<*p_sunwukong<<endl;
    delete p;
    delete p_houzihousun;
    delete p_sundaniang;
    delete p_zhubajie;
    delete p_sunwukong;
    p=p_sunwukong=p_zhubajie=p_houzihousun=p_sundaniang = nullptr;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值