设计模式之原型模式

1.原型模式的意图是什么?

         通过复制一个现有的对象来生成新的对象,而不是通过实例化方式。

2.浅复制和深复制

        Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型。其余的都是浅拷贝。

我们先来看看浅复制后的对象和对象副本的情况:

      设计模式之原型模式_第1张图片

我们再看看看深复制的对象和对象副本的情况:

  设计模式之原型模式_第2张图片

      有图可知,对于值类型的成员浅复制也是在副本中重新创建的成员,对应到内存的栈上,分配新的内存空间。那么对于引用类型则因为浅复制的时候,对象和对象副本共用同一个引用对象,那么不管是在对象还是对象副本中修改了相应的引用成员了之后,那么这个引用类型的成员就会发生变化。因为2个对象指向同一个内存地址,那么任何一个修改操作都会产生改变。

       深复制,不管是值类型的成员还是引用类型的成员,对象和对象副本都指向不同的内存空间,对任何一个成员属性的修改,都不会影响到另一个对象的 值。3.原型模式解读

   1)UML类图

设计模式之原型模式_第3张图片

原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:

  • 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
  • 重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。
 2)代码实现

  JAVA版本:

class Prototype implements Cloneable {
	public Prototype clone(){
		Prototype prototype = null;
		try{
			prototype = (Prototype)super.clone();
		}catch(CloneNotSupportedException e){
			e.printStackTrace();
		}
		return prototype; 
	}
}

class ConcretePrototype extends Prototype{
	public void show(){
		System.out.println("原型模式实现类");
	}
}

public class Client {
	public static void main(String[] args){
		ConcretePrototype cp = new ConcretePrototype();
		for(int i=0; i< 10; i++){
			ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
			clonecp.show();
		}
	}
}

C++版本:通过拷贝构造函数实现

/************************************************************************/
/*							  原型模式                                  */
/************************************************************************/

/*
    c++中原型模式的实现主要是通过拷贝构造函数实现的
*/
#include <IOSTREAM>
using namespace std;


/*
	原型类,声明一个克隆自己的接口
*/
class Prototype
{
public:
	virtual ~Prototype(){};

	//定义一个克隆的抽象函数
	virtual Prototype *Clone() const = 0 ;

protected:
	Prototype()
	{
	}

};

class Wukong : public Prototype
{
public:

	Wukong(int age,char *name)
	{
		this->age = age;
		this->name = name;
	}


	//拷贝构造函数
	Wukong(const Wukong&C)
	{
		age=C.age;
		name = new char[100];
		strcpy(name,C.name);
	}

	//克隆函数
	Prototype *Clone() const
	{
		//当类对象以参数的形式传递时会调用拷贝构造函数
		return new Wukong(*this);
	}


	void Display()
	{
		cout<<"this is a test func"<<endl;
		cout<<"age = "<<age<<endl<<"name = "<<name<<endl;
	}	


private: 
	int age;
	char *name;
};

void main()
{
	//悟空真身
	Wukong *wk = new Wukong(18,"孙悟空");
	wk->Display();

	//分身1
	Wukong *wk1 = (Wukong*)wk->Clone();
	wk1->Display();

	//分身2
	Wukong *wk2 = (Wukong*)wk->Clone();
	wk2->Display();

}

4.原型模式的优点

  1)使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

  2)使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。

5.原型模式的使用场合

  1)对象类型刚开始不能确定,在运行期才能确定。

  2)需要一个对象在某个状态下的副本,例如有的时候我们需要对比一个对象经过处理后的状态和处理前的状态是否发生过改变。

  3)当我们在处理一些对象比较简单,并且对象之间的区别很小,可能只是很固定的几个属性不同的时候。

你可能感兴趣的:(设计模式之原型模式)