介紹
? ? ? ? 使用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過克隆這些原型創(chuàng)建新的對(duì)象。原型模式是一種對(duì)象創(chuàng)建型模式。
實(shí)現(xiàn)
myclass.h
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
class Prototype {
public:
void setId(uint64_t id);
uint64_t getId();
virtual Prototype *clone() = 0;
private:
uint64_t m_id;
};
class ConcretePrototype : public Prototype {
public:
Prototype *clone() override;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
void Prototype::setId(uint64_t id) {
m_id = id;
}
uint64_t Prototype::getId() {
return m_id;
}
Prototype* ConcretePrototype::clone() {
ConcretePrototype *prototype = new ConcretePrototype();
prototype->setId(this->getId());
return prototype;
}
main.cpp
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
Prototype *obj1 = new ConcretePrototype();
std::cout << "obj1: " << std::hex << obj1 << ", id: " << obj1->getId() << std::endl;
auto obj2 = obj1->clone();
std::cout << "obj2: " << std::hex << obj2 << ", id: " << obj2->getId() << std::endl;
delete obj1;
delete obj2;
return 0;
}
總結(jié)
? ? ? ? 優(yōu)點(diǎn):
? ? ? ? 1.?當(dāng)創(chuàng)建新的對(duì)象實(shí)例較為復(fù)雜時(shí),使用原型模式可以簡(jiǎn)化對(duì)象的創(chuàng)建過程,通過復(fù)制一個(gè)已有實(shí)例可以提高新實(shí)例的創(chuàng)建效率。
? ? ? ? 2.?擴(kuò)展性較好。由于在原型模式中提供了抽象原型類,在客戶端可以針對(duì)抽象原型類進(jìn)行編程,而將具體原型類寫在配置文件中,增加或減少具體原型類對(duì)原有系統(tǒng)都沒有任何影響。
? ? ? ? 3.?原型模式提供了簡(jiǎn)化的創(chuàng)建結(jié)構(gòu)。工廠方法模式常常需要有一個(gè)與產(chǎn)品類等級(jí)結(jié)構(gòu)相同的工廠等級(jí)結(jié)構(gòu),而原型模式就不需要這樣。原型模式中產(chǎn)品的復(fù)制是通過封裝在原型類中的克隆方法實(shí)現(xiàn)的,無須專門的工廠類來創(chuàng)建產(chǎn)品。
? ? ? ? 4.?可以使用深克隆的方式保存對(duì)象的狀態(tài)。使用原型模式將對(duì)象復(fù)制一份并將其狀態(tài)保存起來,以便在需要的時(shí)候使用,例如恢復(fù)到某一歷史狀態(tài),可輔助實(shí)現(xiàn)撤銷操作。
? ? ? ? 缺點(diǎn):
? ? ? ??1.?需要為每一個(gè)類配備一個(gè)克隆方法,而且該克隆方法位于一個(gè)類的內(nèi)部。當(dāng)對(duì)已有的類進(jìn)行改造時(shí),需要修改源代碼,違背了開閉原則。
? ? ? ? 2.?在實(shí)現(xiàn)深克隆時(shí)需要編寫較為復(fù)雜的代碼,而且當(dāng)對(duì)象之間存在多重的嵌套引用時(shí),為了實(shí)現(xiàn)深克隆,每一層對(duì)象對(duì)應(yīng)的類都必須支持深克隆,實(shí)現(xiàn)起來可能會(huì)比較麻煩。
? ? ? ? 適用場(chǎng)景:
? ? ? ? 1.?創(chuàng)建新對(duì)象成本較大(例如初始化需要占用較長(zhǎng)的時(shí)間,占用太多的CPU資源或網(wǎng)絡(luò)資源)。新的對(duì)象可以通過原型模式對(duì)已有對(duì)象進(jìn)行復(fù)制來獲得,如果是相似對(duì)象,則可以對(duì)其成員變量稍作修改。
? ? ? ? 2.?如果系統(tǒng)要保存對(duì)象的狀態(tài),而對(duì)象的狀態(tài)變化很小,或者對(duì)象本身占用內(nèi)存較少時(shí),可以使用原型模式配合備忘錄模式(本書第21章介紹)來實(shí)現(xiàn)。
? ? ? ? 3.?需要避免使用分層次的工廠類來創(chuàng)建分層次的對(duì)象,并且類的實(shí)例對(duì)象只有一個(gè)或很少的幾個(gè)組合狀態(tài)。通過復(fù)制原型對(duì)象得到新實(shí)例可能比使用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例更加方便。
練習(xí)
myclass.h
//
// Created by yuwp on 2024/1/12.
//
#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H
#include <iostream>
class Address {
public:
std::string m_name;
uint32_t m_id;
};
class Object {
public:
virtual Object *deepClone() = 0;
virtual Object *clone() = 0;
};
class Customer : public Object {
public:
Customer() {}
Customer(Address *addr);
Address *getAddress();
void setAddress(Address *addr);
Object *deepClone() override;
Object *clone() override;
private:
Address *m_addr;
};
#endif //DESIGNPATTERNS_MYCLASS_H
myclass.cpp文章來源:http://www.zghlxwxcb.cn/news/detail-804815.html
//
// Created by yuwp on 2024/1/12.
//
#include "myclass.h"
Customer::Customer(Address *addr) {
m_addr = addr;
}
Address* Customer::getAddress() {
return m_addr;
}
void Customer::setAddress(Address *addr) {
m_addr = addr;
}
Object* Customer::clone() {
Customer *customer = new Customer();
customer->setAddress(m_addr);
return customer;
}
Object* Customer::deepClone() {
Customer *customer = new Customer();
Address *address = new Address();
address->m_id = m_addr->m_id;
address->m_name = m_addr->m_name;
customer->setAddress(address);
return customer;
}
main.cpp文章來源地址http://www.zghlxwxcb.cn/news/detail-804815.html
#include <iostream>
#include <mutex>
#include "myclass.h"
int main() {
Address *addr = new Address();
addr->m_id = 1;
addr->m_name = "abc";
Object *obj1 = new Customer(addr);
auto obj2 = obj1->clone();
auto obj3 = obj1->deepClone();
std::cout << "obj1: " << std::hex << obj1 << ", addr = " << std::hex << dynamic_cast<Customer *>(obj1)->getAddress() << ", id = " << dynamic_cast<Customer *>(obj1)->getAddress()->m_id << ", name = " << dynamic_cast<Customer *>(obj1)->getAddress()->m_name << std::endl;
std::cout << "obj2: " << std::hex << obj2 << ", addr = " << std::hex << dynamic_cast<Customer *>(obj2)->getAddress() << ", id = " << dynamic_cast<Customer *>(obj2)->getAddress()->m_id << ", name = " << dynamic_cast<Customer *>(obj2)->getAddress()->m_name << std::endl;
std::cout << "obj3: " << std::hex << obj3 << ", addr = " << std::hex << dynamic_cast<Customer *>(obj3)->getAddress() << ", id = " << dynamic_cast<Customer *>(obj3)->getAddress()->m_id << ", name = " << dynamic_cast<Customer *>(obj3)->getAddress()->m_name << std::endl;
return 0;
}
到了這里,關(guān)于《設(shè)計(jì)模式的藝術(shù)》筆記 - 原型模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!