一、原型模式是什么?
原型模式是一种创建型的软件设计模式,通俗的来讲就是复制粘贴。
通过一个原型对象,快速地创建出多个一致的对象,并对其进行相关的操作。比如文件夹中存放了一个Word文件,你把文件复制了一个副本出来,原件不动,对副本进行修改以达到自己的目的。原型像是一个模板,你可以基于它复制好多对象,而复制出来的副本产生任何变化都不会影响到原型(注意:前提是clone的实现要满足深拷贝)。
原型模式的优点:
- 便捷、简洁、高效。不需要考虑对象的复杂程度,只需要复制即可。
- 无需初始化。可动态地获取当前原型的状态,并在当前基础上进行拷贝。
- 允许动态增加或减少产品类。
原型模式的缺点:
- 每个类都需要配备一个clone函数,若对已有的类进行改造,需要修改其源码,违背了开闭原则。
二、原型模式
2.1 结构图
客户端即Main主函数,可基于原型提供的clone方法,拷贝多个对象。
2.2 代码示例
场景描述:我创建了一个Word文件,对其进行复制粘贴,得到多个副本文件。
//Product.h /****************************************************/ #pragma once #include <iostream> using namespace std; // 内容类 class Content { public: // 显式构造函数 explicit Content(string input) :m_text(input) {}; // 析构函数 ~Content() {} // 设置内容 void setText(string input) { m_text = input; } // 获取内容 string getText() { return m_text; } private: string m_text; // 文本内容 }; // 抽象文件类 class File { public: // 构造函数 File(string name) :m_name(name) { m_content = nullptr; }; // 析构函数 virtual ~File() { if (m_content != nullptr) { cout << " 内容地址:" << m_content << endl; delete m_content; m_content = nullptr; } }; // 添加内容 void setContent(string input) { if (m_content == nullptr) { m_content = new Content(input); } else { m_content->setText(input); } } // 输出内容 string getContent() { if (m_content == nullptr) { return ""; } else { return m_content->getText(); } } // 拷贝函数 virtual File* clone() = 0; protected: string m_name; // 文件名字 Content *m_content; // 内容 }; // Word文件类(具体) class WordFile :public File { public: // 构造函数 WordFile(string name) :File(name) { cout << " Word文件类构造,名为:" << name << endl; }; // 析构函数 virtual ~WordFile() { cout << " Word文件类析构。" << endl; }; // 拷贝构造函数 WordFile(const WordFile& file) : File(file) { m_name = file.m_name; cout << " Word文件类拷贝构造,名为:" << m_name << endl; if (file.m_content != nullptr) { m_content = new Content(file.m_content->getText()); } else { m_content = nullptr; } } // 克隆 virtual File* clone() { return new WordFile(*this); } };
//main.cpp /****************************************************/ #include <iostream> #include <string> #include "Product.h" using namespace std; int main() { cout << "创建文件1。" << endl; File* file1 = new WordFile("test"); file1->setContent("今天天气真好!"); cout << "克隆文件1,生成文件2。" << endl; File* file2 = file1->clone(); file2->setContent("肚子饿了。。。"); cout << "删除文件1。" << endl; delete file1; cout << "克隆文件2,生成文件3。" << endl; File* file3 = file2->clone(); cout << "文件3的内容是:" << file3->getContent() << endl; cout << "删除文件3。" << endl; delete file3; cout << "删除文件2。" << endl; delete file2; return 0; }
程序结果如下。
在上述示例中,我们可以看到,除了抽象原型和具体原型,我还创建了一个内容类,并在原型中放入了一个它的指针,这样做是为了让大家直观地看看深拷贝和浅拷贝的区别。原型中的普通变量一般是浅拷贝,通过值传递完成,而指针如果通过new申请了空间,那么拷贝的对象中对应的指针则需要重新new,不然两个指针指向同一地址,若原型进行了析构,那么复制品再次析构时,就会对已经释放过的空间再次释放,进而引起崩溃。
三、总结
我尽可能用较通俗的话语和直观的代码例程,来表述我对原型模式的理解,或许有考虑不周到的地方,如果你有不同看法欢迎评论区交流!希望我举的例子能帮助你更好地理解原型模式。
如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!