23种设计模式(C++)之原型(Prototype)模式

23种设计模式(C++)之原型(Prototype)模式

概念

原型(Prototype)模式,是一种对象创建型模式。

意图

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

理解

    当需要复制一个类的对象,或者需要创建一个与已有对象的信息基本相同的对象时,通常需要对该对象的所有成员信息进行拷贝,这个过程是很耗费资源的。
  原型模式提供一种在类中添加Clone成员函数的方法,通过调用该方法,可快速克隆一个新的对象。

提醒

拷贝包括浅拷贝和深拷贝:
浅拷贝:拷贝者和被拷贝者指向同一内存地址,当一方值发生变化,会影响另一方的值。
深拷贝:因为拷贝时重新分配了资源,因此一方值的变化并不会影响另一方。
在“实例”部分会举例说明这一点,两种拷贝方式都有用途,设计时选择需要的方式即可。

实例

本文以汽车为例,先设计一个含有Clone方法的具体类。

具体类实例

创建汽车具体类
class Car
{
private:
	string gearInfo;
	string bodyworkInfo;
public:
	Car() {}
	void setGearInfo(string geartype) 
	{
		this->gearInfo = geartype;
	}
	string getGearInfo()
	{
		return this->gearInfo;
	}
	void setBodyworkInfo(string bodyworktype)
	{
		this->bodyworkInfo = bodyworktype;
	}
	string getBodyworkInfo()
	{
		return this->bodyworkInfo;
	}
	Car *deepClone()
	{
		return new Car(*this);	//Deep clone
	}
	Car *shallowClone()
	{
		Car *car(this); // shallow clone
		return car;
	}
};
客户端测试
int main()
{
	Car *electricCar = new Car();
	electricCar->setGearInfo("electric car gear");
	electricCar->setBodyworkInfo("white bodywork");
    cout << "Electric car gear info: "<<electricCar->getGearInfo()<<"; Electric car bodywork info:"<<electricCar->getBodyworkInfo()<<endl;
	// Deep clone
	Car *oilCar2 = electricCar->deepClone();
	oilCar2->setGearInfo("oil car gear");
	cout << "Oil car gear info: " << oilCar2->getGearInfo() << "; Oil car bodywork info: " << oilCar2->getBodyworkInfo() << endl;
	cout << "Electric car gear info: " << electricCar->getGearInfo() << "; Electric car bodywork info:" << electricCar->getBodyworkInfo() << endl;
	// Shallow copy
	Car *oilCar1 = electricCar->shallowClone();
	oilCar1->setGearInfo("oil car gear");
	cout << "Oil car gear info: " << oilCar1->getGearInfo() << "; Oil car bodywork info: " << oilCar1->getBodyworkInfo() << endl;
	cout << "Electric car gear info: " << electricCar->getGearInfo() << "; Electric car bodywork info:" << electricCar->getBodyworkInfo() << endl;
}
Result:
Electric car gear info: electric car gear; Electric car bodywork info:white bodywork
Oil car gear info: oil car gear; Oil car bodywork info: white bodywork
Electric car gear info: electric car gear; Electric car bodywork info:white bodywork
Oil car gear info: oil car gear; Oil car bodywork info: white bodywork
Electric car gear info: oil car gear; Electric car bodywork info:white bodywork
Analysis:
  • 对比第一行和第二行结果可以看出:
    拷贝的对象oilCar2直接包含了对象electricCar的成员信息。
  • 通过第二行和第三行的结果可以看出:
    通过深拷贝产生的oilCar2对象,当修改成员信息时,不会影响到electricCar的成员信息。
  • 通过第四行和第五行的结果可以看出:
    通过浅拷贝产生的oilCar1对象,当修改成员信息时,electricCar的成员信息受到了影响。

抽象类实例

为了便于扩展汽车类型并减少修改原有代码,本例采用抽象类实现原型设计模式。

创建汽车抽象类
class CarPrototype
{
protected:
	string gearInfo;
	string bodyworkInfo;
public:
	virtual void setGearInfo(string geartype) = 0;
	virtual string getGearInfo() = 0;
	virtual void setBodyworkInfo(string bodyworktype) = 0;
	virtual string getBodyworkInfo() = 0;
	virtual CarPrototype *carClone() = 0;
};
创建电动汽车类
class ElectricCar : public CarPrototype
{
public:
	void setGearInfo(string geartype)
	{
		this->gearInfo = geartype;
	}
	string getGearInfo()
	{
		return this->gearInfo;
	}
	void setBodyworkInfo(string bodyworktype)
	{
		this->bodyworkInfo = bodyworktype;
	}
	string getBodyworkInfo()
	{
		return this->bodyworkInfo;
	}
	CarPrototype *carClone()
	{
		return new ElectricCar(*this);	//Deep clone
	}
};
客户端测试
int main()
{
	CarPrototype *electricCar1 = new ElectricCar();
	electricCar1->setGearInfo("electric1");
	electricCar1->setBodyworkInfo("white");
	cout << "Electric car 1 gear info: " << electricCar1->getGearInfo() << "; Electric1 car 1 bodywork info:" << electricCar1->getBodyworkInfo() << endl;
	CarPrototype *electricCar2 = electricCar1->carClone();
	electricCar2->setGearInfo("electric2");
	cout << "Electric car 2 gear info: " << electricCar2->getGearInfo() << "; Electric car 2 bodywork info: " << electricCar2->getBodyworkInfo() << endl;
}
Result
Electric car 1 gear info: electric1; Electric1 car 1 bodywork info:white
Electric car 2 gear info: electric2; Electric car 2 bodywork info: white

本例默认采用了深拷贝的方式。
如果需要添加新的汽车类型,比如油动汽车,直接添加油动汽车的继承类即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值