设计模式之原型模式
有些场景中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效。
比如王者里面的小兵,只需创建一个小兵的原型,之后就只需要进行克隆复制就行了。
一、定义
原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型类必须实现cloneable接口,实现clone方法。
二、实例
创建一个小兵的原型
public class BatmanPrototype implements Cloneable{ //横坐标 private double x; //纵坐标 private double y; //血量 private Blood blood; //省略get/set方法 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } 1、血量没有实现Cloneable方法 public class Blood{ private int blood; }
测试类:
BatmanPrototype batmanPrototype = new BatmanPrototype(); batmanPrototype.setX(10d); batmanPrototype.setY(10d); batmanPrototype.setBlood(new Blood(100)); BatmanPrototype cloneObject = (BatmanPrototype) batmanPrototype.clone(); System.out.println("prototype:"+batmanPrototype); System.out.println("clone:"+cloneObject); 1、修改原型血量 batmanPrototype.getBlood().setBlood(99); System.out.println("======================================="); System.out.println("prototype:"+batmanPrototype); System.out.println("clone:"+cloneObject);
结果如下:
我在代码中只修改了原型的血量,但是从结果看,克隆出来的类的血量也被修改了,这就是浅克隆,只是简单的将地址赋值给了对象,只要原型一变,克隆对象也会改变。
概念:
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
那么如何使用深克隆呢?
这就需要重写原型的clone方法以及原型属性需要实现Cloneable接口。
public class BatmanPrototype implements Cloneable{ //横坐标 private double x; //纵坐标 private double y; //血量 private Blood blood; @Override protected Object clone() throws CloneNotSupportedException { BatmanPrototype batmanPrototype = (BatmanPrototype) super.clone(); batmanPrototype.blood = (Blood) this.blood.clone(); return batmanPrototype; } } public class Blood implements Cloneable{ private int blood; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
再用之前的测试类进行测试:
atmanPrototype batmanPrototype = new BatmanPrototype(); batmanPrototype.setX(10d); batmanPrototype.setY(10d); batmanPrototype.setBlood(new Blood(100)); BatmanPrototype cloneObject = (BatmanPrototype) batmanPrototype.clone(); System.out.println("prototype:"+batmanPrototype); System.out.println("clone:"+cloneObject); 1、修改原型血量 batmanPrototype.getBlood().setBlood(99); System.out.println("======================================="); System.out.println("prototype:"+batmanPrototype); System.out.println("clone:"+cloneObject);
结果:
此时克隆对象的血量就不会随着原型变化而变化了。
三、源码实例
实现了Cloneable的接口都属于这种模式。
=======================================================
我是Liusy,一个喜欢健身的程序员。
欢迎关注微信公众号【Liusy01】,一起交流Java技术及健身,获取更多干货,领取Java进阶干货,一起成为Java大神。
来都来了,关注一波再溜呗。