常用设计模式之 - 原型模式

版权声明:QQ:763905926 未经允许请勿转载,转载请注明出处! https://blog.csdn.net/lms1008611/article/details/89609631

    在西游记中,我们常看到孙悟空用自己的猴毛变出很多个特征跟自己一模一样的"孙悟空"来, 可能仅仅是名字不一样,孙悟空二弟、孙悟空三弟、孙悟空四弟,除了名字不一样外,其他的特征完全一模一样,这个通过孙悟空创建出的多个跟自己一模一样的克隆品,在设计模式里头,我们称之为:原型模式

    在开始讲解之前,还是以一个场景来描述下这个需求,在我们工作中,常常要写日报,一个小组内的成员日报格式一样,那么久很有可能两个人当天做的工作时一样的,那么体现在日报中的信息,仅仅是名字不同。

    将这个设计成类,可以设计为如下(包含姓名、日期、工作内容)

class WeekLog
{
private:
    string m_name;    //姓名
    string m_date;    //日期
    string m_content; //工作内容

public:

    WeekLog(string name,string date,string content)
    {
        m_name = name;
        m_date = date;
        m_content = content;
    }

    string setName(string name) 
    {
        m_name = name;
    }
    string setDate(string date) 
    {
        m_date = date;
    }
    string setContent(string content) 
    {
        m_content = content;
    }
    string getName() 
    {
        return m_name;
    }
    string getDate() 
    {
        return m_date;
    }
    string getContent()
    {
        return m_content;
    }
};

那么可以按照如下方式使用这个类

int main(int argc, char* argv[])
{
    //Tom与Jack的日报中日期、工作内容都一样
    WeekLog TomWeekLog("Tom","20190427","Bug Fix!");   
    WeekLog JackWeekLog("Jack","20190427","Bug Fix!");

    cout << TomWeekLog.getName() << endl;
    cout << TomWeekLog.getDate() << endl;
    cout << TomWeekLog.getContent() << endl;

    cout << JackWeekLog.getName() << endl;
    cout << JackWeekLog.getDate() << endl;
    cout << JackWeekLog.getContent() << endl;

    return 0;
}

这么使用当然是没问题的。
但是注意上边Tom与Jack的日报信息,除了名字不同外,日期跟工作内容都是相同的,而在 定义Jack的日报信息时,把所有的内容都重设定了一遍,这显得有点累赘了。

为了解决这个问题,我们引入了原型设计模式:在类中增加一个clone函数,自己new自己后返回一个新的自己。(想想孙悟空自己复制自己)
代码实现则很简单,如下:

class WeekLog
{
private:
    string m_name;
    string m_date;
    string m_content;

public:

    WeekLog(string name,string date,string content)
    {
        m_name = name;
        m_date = date;
        m_content = content;
    }
    WeekLog(const WeekLog& obj) //拷贝构造函数
    {
        m_name = obj.m_name;
        m_date = obj.m_date;
        m_content = obj.m_content;
    }
    WeekLog& operator=(const WeekLog& obj) //赋值构造函数
    {
        if(this != &obj)
        {
            m_name = obj.m_name;
            m_date = obj.m_date;
            m_content = obj.m_content;
        }
        return *this;
    }
    virtual string setName(string name) 
    {
        m_name = name;
    }
    virtual string setDate(string date) 
    {
        m_date = date;
    }
    virtual string setContent(string content) 
    {
        m_content = content;
    }
    virtual string getName() 
    {
        return m_name;
    }
    virtual string getDate() 
    {
        return m_date;
    }
    virtual string getContent()
    {
        return m_content;
    }

    //克隆操作,返回一个new 后的自己
    WeekLog* clone()
    {
        return new WeekLog(*this); //这里使用拷贝构造函数,即new后得到的对象跟原对象信息一致
    }
};

下边来使用下:

int main(int argc, char* argv[])
{
    WeekLog TomWeekLog("Tom","20190427","Bug Fix!");
    WeekLog* JackWeekLog = TomWeekLog.clone(); //从现有对象克隆一份
    JackWeekLog->setName("Jack"); //修改下名字即可

    cout << TomWeekLog.getName() << endl;
    cout << TomWeekLog.getDate() << endl;
    cout << TomWeekLog.getContent() << endl;

    cout << JackWeekLog->getName() << endl;
    cout << JackWeekLog->getDate() << endl;
    cout << JackWeekLog->getContent() << endl;

    delete JackWeekLog;

    return 0;
}

编译运行

可以看到,只有名字不一样,其他信息都是一样的,并且在生成Jack的日报时,也不需要重设所有项

猜你喜欢

转载自blog.csdn.net/lms1008611/article/details/89609631