プロトタイプモード
プロトタイプモードのアイデアは、既存のオブジェクトをコピーすることによって、1つ以上の同一または類似のオブジェクトを取得することです。
プロトタイプモードの動作原理は、プロトタイプオブジェクトを作成するオブジェクト(クライアント)に渡すことです。クライアントは、プロトタイプオブジェクトに自分自身をコピーするように要求することにより、作成プロセスを実現します。ファクトリアプローチから理解するために、作成される新しいファクトリオブジェクトはプロトタイプクラス自体です。
ソフトウェアシステム内の一部のオブジェクトの作成プロセスはより複雑で、頻繁に作成する必要がある場合があります。プロトタイプモードでは、プロトタイプオブジェクトを指定して作成するオブジェクトのタイプを指定し、をコピーして同じタイプのオブジェクトをさらに作成します。プロトタイプオブジェクト。、これはプロトタイプパターンの意図です。
プロトタイプ構造
プロトタイプ構造には、次の役割が含まれます。
- 抽象プロトタイプ:クローン自体のインターフェースを宣言します
- 具体的なプロトタイプクラス(ConcretePrototype):クローンインターフェイスを実装します
- クライアント:抽象プロトタイプクラスがクライアントで宣言され、具体的なプロトタイプクラスオブジェクトインスタンスが顧客のニーズに応じて複製されます
浅いコピー、深いコピー
プロトタイプパターンはクラス自体のコピーであると言えますが、このコピーはコードのコピーではなく、オブジェクトに含まれるすべての属性のコピーです。ただし、コピー操作が異なると、浅いコピーと深いコピーに分けられる2つの異なるコピーが生成される場合があります。
浅いコピー
浅いコピーでは、プロトタイプオブジェクトのメンバー変数が値タイプ(int、double、char、その他の基本データ型など)の場合、コピーはコピーオブジェクトにコピーされます。プロトタイプオブジェクトのメンバー変数が参照/ポインタ、参照されます/ポインタが指すアドレスはコピーオブジェクトにコピーされます。つまり、プロトタイプオブジェクトのメンバー変数とコピーオブジェクトは同じアドレスを指します。
ディープコピー
ディープコピーでは、プロトタイプオブジェクトのメンバー変数が値型であるかポインタ/参照型であるかに関係なく、コピーはコピーオブジェクトにコピーされます。
ディープコピーでは、ポインタ/参照オブジェクトもコピーオブジェクトにコピーされることに注意してください。
プロトタイプパターンの例
protocol_pattern.h
#include <iostream>
#include <string.h>
using namespace std;
//work model类
class WorkModel
{
public:
string modelName;
void setWorkModelName(string iName){
this->modelName = iName;
}
};
//抽象原型类PrototypeWork
class PrototypeWork
{
public:
PrototypeWork(){
}
virtual PrototypeWork *clone() = 0;
private:
};
//具体原型类ConcreteWork
class ConcreteWork :public PrototypeWork
{
public:
ConcreteWork(){
}
ConcreteWork(string iName, int iIdNum, string modelName){
this->name = iName;
this->idNum = iIdNum;
this->workModel = new WorkModel();
this->workModel->setWorkModelName(modelName);
}
ConcreteWork *clone(){
ConcreteWork *work = new ConcreteWork();
work->setName(this->name);
work->setIdNum(this->idNum);
work->workModel = this->workModel;
return work;
}
void setName(string iName){
this->name = iName;
}
void setIdNum(int iIdNum){
this->idNum = iIdNum;
}
void setModel(WorkModel *iWorkModel){
this->workModel = iWorkModel;
}
//打印work信息
void printWorkInfo(){
cout << "name:\t" << this->name << endl;
cout << "idNum:\t" << this->idNum << endl;
cout << "modelName:\t" << this->workModel->modelName << endl;
}
// private:
string name;
int idNum;
WorkModel *workModel;
};
protocol_pattern.cpp
#include "prototype_pattern.h"
int main()
{
// 赋值
#if 0
ConcreteWork *BasicWork = new ConcreteWork("basic", 1001, "basic_Model");
cout << "\nBasic Work:\n";
BasicWork->printWorkInfo();
ConcreteWork *CopyWork = BasicWork;
cout << "\nCopy Work:\n";
CopyWork->printWorkInfo();
cout << "\nCopy 完成后,记得跟新WorkName,Num以及ModelName!\n";
CopyWork->setName("CopyWork");
CopyWork->setIdNum(1002);
WorkModel *CopyModel = new WorkModel();
CopyModel->setWorkModelName("Copy_Model");
CopyWork->setModel(CopyModel);
cout << "\nBasic Work \n";
BasicWork->printWorkInfo();
cout << "\nCopy Work \n";
CopyWork->printWorkInfo();
delete CopyModel;
delete CopyWork;
#else
// 克隆
ConcreteWork *BasicWork = new ConcreteWork("basic", 1001, "Basic_Model");
cout << "\nBasic Work:\n";
BasicWork->printWorkInfo();
ConcreteWork *CopyWork = BasicWork->clone();
cout << "\nCopy Work:\n";
CopyWork->printWorkInfo();
cout << "\nCopy 完成后,记得跟新WorkName,Num以及ModelName !\n";
CopyWork->setName("CopyWork");
CopyWork->setIdNum(1002);
WorkModel *CopyModel = new WorkModel();
CopyModel->setWorkModelName("Copy_Model");
CopyWork->setModel(CopyModel);
//检查下是否改对了
cout << "\nBasic Work \n";
BasicWork->printWorkInfo();
cout << "\nCopy Work \n";
CopyWork->printWorkInfo();
delete BasicWork;
delete CopyModel;
delete CopyWork;
#endif
return 0;
}
比較割り当てとコピーの違いに注意してください
プロトタイプモードの概要
利点:
- 新しいオブジェクトインスタンスの作成がより複雑な場合、プロトタイプモードを使用すると、作成プロセスが簡素化され、オブジェクト作成の効率が向上します。
- 拡張可能:抽象的なプロトタイプクラスがパターンで提供され、具体的なプロトタイプクラスを適切に拡張できます。
- 作成構造は単純です。ファクトリの作成はプロトタイプオブジェクト自体です。
短所:
- ディープクローンコードはより複雑です。
- 各クラスにはcloneメソッドが装備されている必要があり、メソッドはクラス内に配置されているため、変更すると開閉するという原則に違反します。
該当する環境:
- 新しいオブジェクトインスタンスの作成がより複雑な場合、プロトタイプモードで作成プロセスを簡素化できます。
- 第3条の利点を組み合わせると、階層ファクトリクラスを使用して階層オブジェクトを作成することを避ける必要があり、クラスのインスタンスオブジェクトには、1つまたは少数の結合状態しかありません。プロトタイプオブジェクトをコピーして新しいインスタンスを取得することにより、コンストラクターを使用するよりも優れています。新しいインスタンスを作成する方が便利です。