KnightOnHorse的博客

追求技术的道路永无止境

Creational.Prototype原型模式:深拷贝、浅拷贝、写时拷贝

思考原型模式

  ①原型模型的本质克隆生成对象

  ②原型模式可以用来解决“只知接口而不知实现的问题”,出现一种“接口造接口”的假象。

  ③原型模式的重心还是在创建新的对象实例。至于创建出来的对象,其属性的值是否一定要和原型对象完全一样,这并没有强制规定,但一般会拷贝成一样的。

  ④通过克隆出来实例是原型实例是两个完全独立的实例,他们之间没有关联。

【编程实验】订单拆分处理

//创建型模式:原型模式//订单处理:
/*
    功能需求:因每个工作小组的处理能力上限是1000,现要求每当订单预定产品数量超过1000时,
把订单拆分为两份来保存,如果还是超过1000,那就继续拆分,直到不超过1000.

*/


//声明文件

#include <iostream>
#include <string>
#include <sstream>

using namespace std;
//*************************辅助类:************************
//定义产品原型的接口,这个产品是为了演示深拷贝
class CProductPrototype{
private:
	string strId;//产品编号
	string strName;//产品名称
public:
	void SetId(string id);
	string GetId();
	void SetName(string name);
	string GetName();
	string ToStr();
	CProductPrototype* Clone();//克隆方法
};

//*************************订单原型**************************

//订单的接口,声明了可以克隆自身的方法
class CAbsOrder{
public:
	virtual ~CAbsOrder();
	virtual string ToStr() = 0;
	virtual void SetName(string name) = 0;
	virtual string GetName() = 0;
	virtual void SetProduct(CProductPrototype* product) = 0;
	virtual CProductPrototype* GetProduct() = 0;
	virtual void SetProductId(string productid) = 0;
	virtual string GetProductId() = 0;
	virtual void SetProductNum(int products) = 0;
	virtual int GetProductNum() = 0;

	virtual CAbsOrder* Clone() = 0;
};

//个人订单对象
class CPersonalOrder : public CAbsOrder{
private:
	string strCustomer;
	CProductPrototype* pProduct;
	string strProductId;
	int iProducts;
public:
	CPersonalOrder();
	~CPersonalOrder();
	void SetName(string customer);
	string GetName();
	void SetProduct(CProductPrototype* product);
	CProductPrototype* GetProduct();
	void SetProductId(string productid);
	string GetProductId();
	void SetProductNum(int products);
	int GetProductNum();
	string ToStr();
	CAbsOrder* Clone();
};

//企业订单对象
class CEnterpriseOrder : public CAbsOrder{
private:
	string strEnterprise;
	CProductPrototype* pProduct;
	string strProductId;
	int iProducts;
public:
	CEnterpriseOrder();
	string ToStr();
	void SetName(string enterprise);
	string GetName();
	void SetProduct(CProductPrototype* product);
	CProductPrototype* GetProduct();
	void SetProductId(string productid);
	string GetProductId();
	void SetProductNum(int products);
	int GetProductNum();
	CAbsOrder* Clone();
};

//*********************************订单拆分过程********************
//处理订单
//saveOrder传入的是订单接口类型的对象实例,这里只知道
//订单接口的类型,并不知道其具体类型是个人订单还是企业订单
void OrderDispatch(CAbsOrder* pOrgOrder);

//实现文件

//*************************辅助类:************************
//定义产品原型的接口,这个产品是为了演示深拷贝
void CProductPrototype::SetId(string id){strId = id;}
string CProductPrototype::GetId(){return strId;}
void CProductPrototype::SetName(string name){strName = name;}
string CProductPrototype::GetName(){return strName;}
string CProductPrototype::ToStr(){return "Id : " + strId + ", Name : " + strName + "\n";}
CProductPrototype* CProductPrototype::Clone()//克隆方法
{
	//创建一个新的订单,然后把本实例的数据复制过去
	CProductPrototype* pProduct = new CProductPrototype();
	pProduct->SetId(strId);
	pProduct->SetName(strName);
	return pProduct;
}

//*************************订单原型**************************

//订单的接口,声明了可以克隆自身的方法
CAbsOrder::~CAbsOrder(){}
//个人订单对象
CPersonalOrder::CPersonalOrder(){pProduct = NULL; iProducts = 0;}
CPersonalOrder::~CPersonalOrder(){cout << "deleting..." << endl << endl; if(pProduct != NULL)			delete pProduct;}
void CPersonalOrder::SetName(string customer){strCustomer = customer;}
string CPersonalOrder::GetName(){return strCustomer;}
void CPersonalOrder::SetProduct(CProductPrototype* product){pProduct = product;}
CProductPrototype* CPersonalOrder::GetProduct(){return pProduct;}
void CPersonalOrder::SetProductId(string productid){strProductId = productid;}
string CPersonalOrder::GetProductId(){return strProductId;}
void CPersonalOrder::SetProductNum(int products){iProducts = products;}
int CPersonalOrder::GetProductNum(){return iProducts;}
string CPersonalOrder::ToStr()
{
	ostringstream oss; oss << iProducts;
	return ("PersonalOrder's Order\nCustomer : " + strCustomer + ", Name : " +
		pProduct->GetName() + ", Id : " + pProduct->GetId() + ", Num : " + oss.str() + ".");
}
CAbsOrder* CPersonalOrder::Clone()
{
	CAbsOrder* pOrder = new CPersonalOrder();
	pOrder->SetName(strCustomer);
	pOrder->SetProduct(pProduct->Clone());//深度克隆
	pOrder->SetProductNum(iProducts);
	return pOrder;
}


CEnterpriseOrder::CEnterpriseOrder(){pProduct = NULL; iProducts = 0;}
string CEnterpriseOrder::ToStr()
{
	ostringstream oss; oss << iProducts;
	return ("EnterpriseOrder's Order\nEnterprise : " + strEnterprise + ", Name : " + 
		pProduct->GetName() + ", Id : " + pProduct->GetId() + ", Num : " + oss.str() + ".\n");
}
void CEnterpriseOrder::SetName(string enterprise){strEnterprise = enterprise;}
string CEnterpriseOrder::GetName(){return strEnterprise;}
void CEnterpriseOrder::SetProduct(CProductPrototype* product){pProduct = product;}
CProductPrototype* CEnterpriseOrder::GetProduct(){return pProduct;}
void CEnterpriseOrder::SetProductId(string productid){strProductId = productid;}
string CEnterpriseOrder::GetProductId(){return strProductId;}
void CEnterpriseOrder::SetProductNum(int products){iProducts = products;}
int CEnterpriseOrder::GetProductNum(){return iProducts;}
CAbsOrder* CEnterpriseOrder::Clone()
{
	CAbsOrder* pOrder = new CEnterpriseOrder();
	pOrder->SetName(strEnterprise);
	pOrder->SetProduct(pProduct->Clone());
	pOrder->SetProductNum(iProducts);
	return pOrder;
}
//*********************************订单拆分过程********************
//处理订单
//saveOrder传入的是订单接口类型的对象实例,这里只知道
//订单接口的类型,并不知道其具体类型是个人订单还是企业订单
void OrderDispatch(CAbsOrder* pOrgOrder)
{
	//1:判断当前的预定产品数量是否大于1000
	int iNew = 0;
	while(pOrgOrder->GetProductNum() > 1000){
		//2.如果大于,还需要继续拆分
		//2.1 再新建一份订单,跟传入的订单除了数量不一样外,
		//其他都相同            
		//如果不采用克隆的方式,下面这行是不知道如何new一个
		//对象的,因为order只是个接口,不能直接实例化。而
		//Clone的作用在运行时order这个具体的对象是知道自己的类型的
		//所以可以通过自身克隆出一个新的对象。
		CAbsOrder* pNewOrder = pOrgOrder->Clone();
		//然后进行赋值,产品数量为1000
		pNewOrder->SetProductNum(1000);
		//2.2 原来的订单保留,把数量减少1000
		pOrgOrder->SetProductNum(pOrgOrder->GetProductNum()-1000);
		//然后是业务处理功能,省略了,打印输出看一下
		cout << "Split Order" << ++iNew << " : " << pNewOrder->ToStr() << endl;
		delete pNewOrder;
	}
}





//客户端

void main()
{
	//创建订单对象,这里为了演示简单,直接new了
	CAbsOrder* pOrgOrder = new CPersonalOrder();
	CProductPrototype* pProduct = new CProductPrototype();
	//设置产品
	pProduct->SetName("Product"); pProduct->SetId("9527");
	//设置订单数据
	pOrgOrder->SetName("Tony");
	pOrgOrder->SetProductNum(2925);
	pOrgOrder->SetProduct(pProduct);

	OrderDispatch(pOrgOrder);//调用业务来保存订单对象
	cout << "Now OrgOrder" << " : " << pOrgOrder->ToStr() << endl;
	delete pOrgOrder;

}

阅读更多
版权声明:本文为博主原创文章,允许转载,转载请注明出处。 https://blog.csdn.net/KnightOnHourse/article/details/79974111
上一篇项目经理,一个Java程序员和一个C++程序员
下一篇Structural.Adapter适配器模式:新接口,老方法
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭