设计模式(6)原型模式

原型模式

原型模式的思路是,通过复制一个已有对象来获取一个或者多个相同或者相似的对象。

原型模式的工作原理是将一个原型对象传给要发动创建的对象------客户端,客户端通过请求原型对象复制本身来实现创建过程。按照工厂方式的思路去理解,就是创建的新工厂对象就是原型类自己。

软件系统中有些对象的创建过程比较复杂,且有时需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在。

原型模式结构

原型式的结构包含以下几个角色:

  • 抽象原型类(AbstractPrototype):声明克隆clone自身的接口
  • 具体原型类(ConcretePrototype):实现clone接口
  • 客户端(Client):客户端中声明一个抽象原型类,根据客户需求clone具体原型类对象实例
    在这里插入图片描述

浅拷贝、深拷贝

原型模式可以说是复制类本身,但这个复制不是代码的复制,而是将对象包含的所有属性都创建一份拷贝。但不同的复制操作,可能会产生两种不同的拷贝,分为浅拷贝和深拷贝。

浅拷贝

在浅拷贝中,如果原型对象的成员变量是值类型(如int、double、char等基本数据类型),将复制一份给拷贝对象;如果原型对象的成员变量是引用/指针,则将引用/指针指向的地址拷贝一份给拷贝对象,即原型对象和拷贝对象中的成员变量指向同一个地址。

深拷贝

在深拷贝中,无论原型对象中的成员变量是值类型还是指针/引用类型,都将复制一份给拷贝对象。
注意,深拷贝中,指针/引用对象也会被拷贝一份给拷贝对象。

原型模式实例

prototype_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;
};

prototype_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条,需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少几个的组合状态,通过复制原型对象得到新实例,比通过使用构造函数创建一个新实例会更加方便。

猜你喜欢

转载自blog.csdn.net/qq_24649627/article/details/115209168