它允许对象通过复制(克隆)自身来创建新的对象,而不是通过
new
关键字直接实例化(通过拷贝构造来实现对象的创建)。这样可以提高对象创建的效率,尤其是对于创建代价较高的对象,避免每次都重新初始化。
如果所需对象与预先配置的对象相同, 那么你只需克隆原型即可,
无需新建一个对象。
例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 #include <iostream> #include <memory> #include <unordered_map> class Document {public : virtual ~Document () = default ; virtual std::unique_ptr<Document> clone () const = 0 ; virtual void show () const = 0 ; };class TextDocument : public Document {public : explicit TextDocument (std::string content) : content(std::move(content)) { } std::unique_ptr<Document> clone () const override { return std::make_unique <TextDocument>(*this ); } void show () const override { std::cout << "Text Document: " << content << std::endl; }private : std::string content; };class ImageDocument : public Document {public : explicit ImageDocument (std::string imagePath) : imagePath(std::move(imagePath)) { } std::unique_ptr<Document> clone () const override { return std::make_unique <ImageDocument>(*this ); } void show () const override { std::cout << "Image Document: " << imagePath << std::endl; }private : std::string imagePath; };class PrototypeManager {public : void registerPrototype (const std::string& key, std::unique_ptr<Document> prototype) { prototypes[key] = std::move (prototype); } std::unique_ptr<Document> create (const std::string& key) { if (prototypes.find (key) != prototypes.end ()) { return prototypes[key]->clone (); } return nullptr ; }private : std::unordered_map<std::string, std::unique_ptr<Document>> prototypes; };
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int main () { PrototypeManager manager; manager.registerPrototype ("text" , std::make_unique <TextDocument>("Hello, Prototype!" )); manager.registerPrototype ("image" , std::make_unique <ImageDocument>("image.png" )); auto doc1 = manager.create ("text" ); auto doc2 = manager.create ("text" ); if (doc1) doc1->show (); if (doc2) doc2->show (); doc1->setData ("test" ); if (doc1) doc1->show (); if (doc2) doc2->show (); auto doc3 = manager.create ("text" ); if (doc3) doc3->show (); return 0 ; }
把创建好的对象存储在容器中(unordered_map),需要该对象就从容器中“克隆”(拷贝)一份出来,得到的这个对象和原对象是两个独立的对象。
注意:可能导致深拷贝问题 ,即如果对象包含指针或动态资源,可能需要手动实现深拷贝。
如果 clone()
实现的是浅拷贝 ,则两个对象共享相同的资源;如果实现的是深拷贝 ,则两个对象完全独立,互不影响。