23种设计模式之原型模式

上一节 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());
		
	}
}

测试结果:

com.prototype.demo.Sheep@15db9742
多莉
Sat May 23 20:05:13 CST 1970
Sat Mar 08 07:55:21 CST 1980
com.prototype.demo.Sheep@5c647e05
多莉
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());
		
	}
}

测试结果:

com.prototype.demo.Sheep@15db9742
多莉
Sat May 23 20:05:13 CST 1970
Sat Mar 08 07:55:21 CST 1980
com.prototype.demo.Sheep@6d311334
多莉
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种设计模式之适配器模式

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值