欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

23种设计模式之原型模式

程序员文章站 2022-06-13 08:03:54
...

上一节 23种设计模式之建造者模式

原型模式场景:

1、通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

2、就是Java种的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点。

3、优势有:效率高(直接克隆,避免了重新执行构造过程步骤)。

4、克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后,再修改克隆对象的值。

原型模式实现:

1、Cloneable接口和clone方法(clone不是Cloneable中的方法)

2、Prototype模式中实现起来最困难的地方就是内存复制操作,所幸再Java中提供了clone()方法替我们做了绝大部分事情。


Sheep类:

public class Sheep implements Cloneable,Serializable{
	private String name;
	private Date date;
	
	/**
	 * 浅克隆
	 */
//	@Override
//	protected Object clone() throws CloneNotSupportedException {
//		Object obj=super.clone();
//		return obj;
//	}
	
	/**
	 * 深克隆
	 */
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj=super.clone();
		
		//深克隆
		Sheep sheep=(Sheep) obj;
		sheep.date=(Date) this.date.clone();
		
		return obj;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}
	
	public Sheep(String name,Date date) {
		this.name=name;
		this.date=date;
	}
	public Sheep() {
	}
}

原型模式可分为浅克隆和深克隆

浅克隆测试:

public class Test1 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Date date=new Date(12312313123L);
		Sheep s1=new Sheep("多莉", date);
		Sheep s2=(Sheep) s1.clone();//此处克隆
		
		System.out.println(s1);
		System.out.println(s1.getName());
		System.out.println(s1.getDate());
		
		//此时改变日期值,当浅克隆时,s2会改变;当深克隆时,s2不会改变
		date.setTime(321321321321L);
		System.out.println(s1.getDate());
		
		System.out.println(s2);
		System.out.println(s2.getName());
		System.out.println(s2.getDate());
		
	}
}

测试结果:

[email protected]
多莉
Sat May 23 20:05:13 CST 1970
Sat Mar 08 07:55:21 CST 1980
[email protected]
多莉
Sat Mar 08 07:55:21 CST 1980

深克隆测试:

public class Test2 {
	public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
		Date date=new Date(12312313123L);
		Sheep s1=new Sheep("多莉", date);
		
		System.out.println(s1);
		System.out.println(s1.getName());
		System.out.println(s1.getDate());
		
		//使用序列化和反序列化实现深克隆
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		ObjectOutputStream  	oos=new ObjectOutputStream(bos);
		oos.writeObject(s1);
		byte[] bytes=bos.toByteArray();
		
		ByteArrayInputStream	bis=new ByteArrayInputStream(bytes);
		ObjectInputStream		ois=new ObjectInputStream(bis);
		Sheep s2=(Sheep) ois.readObject();//克隆好的对象
		
		date.setTime(321321321321L);//此时改变日期值,s2不会改变
		System.out.println(s1.getDate());
		
		System.out.println(s2);
		System.out.println(s2.getName());
		System.out.println(s2.getDate());
		
	}
}

测试结果:

[email protected]
多莉
Sat May 23 20:05:13 CST 1970
Sat Mar 08 07:55:21 CST 1980
[email protected]
多莉
Sat May 23 20:05:13 CST 1970

普通new方法和clone方法的比较

重写clone方法类:

class Laptop implements Cloneable{
	public Laptop(){
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj=super.clone();
		return obj;
	}
}

测试类:

public class Test3 {
	public static void buildNew(int size){
		long start=System.currentTimeMillis();
		for(int i=0;i<size;i++){
			Laptop laptop=new Laptop();
		}
		
		long end=System.currentTimeMillis();
		System.out.println("new方法:"+(end-start));
	}
	
	public static void buildClone(int size) throws CloneNotSupportedException{
		long start=System.currentTimeMillis();
		Laptop laptop=new Laptop();
		for(int i=0;i<size;i++){
			Laptop laptop2=(Laptop) laptop.clone();
		}
		long end=System.currentTimeMillis();
		System.out.println("clone方法:"+(end-start));
	}
	
	public static void main(String[] args) throws CloneNotSupportedException {
		buildNew(1000);
		buildClone(1000);
	}
}

测试结果:

new方法:1699
clone方法:2

明显clone方法效率更高!

原型模式优点:

1、性能优良

原型模型是在内存二进制流的拷贝,要比直接new一个对象性能要好得多,特别是要在一个循环体内产生大量对象时,可以更好的体现。

2、逃避构造函数的约束

即使优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,减少了约束,在实际应用是需要考虑。

开发中的应用场景:

原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。

1、资源优化场景

类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。

2、性能和安全要求的场景

通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

3、一个对象多个修改者的场景

一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。

 


下一节  23种设计模式之适配器模式