Prototype原型模式

浅拷贝:就是给对象中的每个成员变量进行复制,就是把A1类中的变量直接赋给A2类中变量,属于值传递,但是涉及到有new之类内存分配的地方,他们却是共享内存的。

深拷贝:就是不仅使用值传递,而是要每个变量都有自己一份独立的内存空间,互不干扰。

Prototype声明一个复制自身的接口

ConcretePrototype实现一个复制自身的操作

Client让一个原型复制自身从而创建一个新的对象

适用场合

1.当我们的对象类型不是开始就能确定的,而这个类型是在运行期确定的话,那么我们通过这个类型的对象克隆出一个新的对象比较容易一些;

2.有的时候,我们需要一个对象在某个状态下的副本,此时,我们使用原型模式是最好的选择;例如:一个对象,经过一段处理之后,其内部的状态发生了变化;这个时候,我们需要一个这个状态的副本,如果直接new一个新的对象的话,但是它的状态是不对的,此时,可以使用原型模式,将原来的对象拷贝一个出来,这个对象就和之前的对象是完全一致的了;

3.当我们处理一些比较简单的对象时,并且对象之间的区别很小,可能就几个属性不同而已,那么就可以使用原型模式来完成,省去了创建对象时的麻烦了;

4.有的时候,创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。

优点:

1.使用拷贝模式比直接new一个对象的开销要小的多。

2.可以在程序运行时(对象属性发生了变化),得到一份内容相同的实例,但之间还不会相互干扰。

原型模式的优缺点:

  优点:(1):当创建对象的实例较为复杂的时候,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高实例的创建效率。

     (2):扩展性好,由于原型模式提供了抽象原型类,在客户端针对抽象原型类进行编程,而将具体原型类写到配置文件中,增减或减少产品对原有系统都没有影响。

     (3):原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式不需要这样,圆形模式中产品的复制是通过封装在类中的克隆方法实现的,无需专门的工厂类来创建产品。

     (4):可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

  缺点:(1):需要为每一个类配置一个克隆方法,而且该克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。

     (2):在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重签到引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。

原型模式的适用环境:

  1:创建新对象成本较大(例如初始化时间长,占用CPU多或占太多网络资源),新对象可以通过复制已有对象来获得,如果相似对象,则可以对其成员变量稍作修改。

  2:系统要保存对象的状态,而对象的状态很小。

  3:需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的组合状态,通过复制原型对象得到新实例可以比使用构造函数创建一个新实例更加方便。

如果创建新对象成本较大,可以利用已有的对象进行复制来获得。
如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。
需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。
 

//prototype.h
#pragma once

#ifndef PROTOTYPE_H
#define PROTOTYPE_H
#include <iostream>
using namespace std;
class Prototype
{
protected:
	Prototype() { cout << "Prototype构造"<< endl; }
public:
	virtual ~Prototype() { cout << "~Prototype析造" << endl; }
	virtual Prototype* clone() const= 0;
	virtual void printname() = 0;
};

#endif // !PROTOTYPE_H


//ConcretePrototype1.h
#pragma once

#ifndef CONCRETE_PROTOTYPE_H
#define CONCRETE_PROTOTYPE_H

#include "prototype.h"
#include <iostream>
#include <string>
using namespace std;

class ConcretePrototype1 :public Prototype
{
public:
	ConcretePrototype1(string name);
	~ConcretePrototype1();
	ConcretePrototype1(const ConcretePrototype1&other);
	virtual Prototype* clone() const;
	void printname();
private:
	string m_strName;
};


#endif // !CONCRETE_PROTOTYPE_H

//ConcretePrototype1.cpp
#include "ConcretePrototype1.h"

ConcretePrototype1::ConcretePrototype1(string name)
{
	m_strName = name;
	cout << "调用了ConcretePrototype1的构造函数" << endl;
}

ConcretePrototype1::~ConcretePrototype1()
{
	cout << "调用了ConcretePrototype1的析构函数" << endl;
}

ConcretePrototype1::ConcretePrototype1(const ConcretePrototype1 &other)
{
	m_strName = other.m_strName;
	cout << "调用了ConcretePrototype1的拷贝构造函数" << endl;
}

Prototype * ConcretePrototype1::clone() const
{
	cout << "克隆" << endl;
	return new ConcretePrototype1(*this);
}



void ConcretePrototype1::printname()
{
	cout << m_strName<< endl;
}


//main.cpp

#include "prototype.h"
#include <iostream>
#include "ConcretePrototype1.h"
using namespace std;

int main()
{
	Prototype* p = new ConcretePrototype1("rand");

	Prototype* p1 = p->clone();
	Prototype* p2 = p1->clone();
	p1->printname();
	p2->printname();
	delete p; 
	p = NULL;
	delete p1;
	p = NULL;
	delete p2;
	p = NULL;
	system("pause");
	return 0;
}

 Prototype模式和Builder模式、AbstractFactory模式都是通过一个类(对象实例)来专门负责对象的创建工作(工厂对象),它们之间的区别是:Builder模式重在复杂对象的一步步创建(并不直接返回对象),AbstractFactory模式重在产生多个相互依赖类的对象,而Prototype模式重在从自身复制自己创建新类。

猜你喜欢

转载自blog.csdn.net/qq_38753888/article/details/85330826