类图
实例
public interface Prototype{ Prototype clone(); }
public class ConcretePrototypeA implements Prototype { private int age; private String name; private List hobbies; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getHobbies() { return hobbies; } public void setHobbies(List hobbies) { this.hobbies = hobbies; } @Override public ConcretePrototypeA clone() { ConcretePrototypeA concretePrototype = new ConcretePrototypeA(); concretePrototype.setAge(this.age); concretePrototype.setName(this.name); concretePrototype.setHobbies(this.hobbies); return concretePrototype; } }
public class ConcretePrototypeB implements Prototype { @Override public Prototype clone() { return null; } }
public class Client { private Prototype prototype; public Client(Prototype prototype){ this.prototype = prototype; } public Prototype startClone(Prototype concretePrototype){ return (Prototype)concretePrototype.clone(); } }
public class PrototypeTest { public static void main(String[] args) { // 创建一个具体的需要克隆的对象 ConcretePrototypeA concretePrototype = new ConcretePrototypeA(); // 填充属性,方便测试 concretePrototype.setAge(18); concretePrototype.setName("prototype"); List hobbies = new ArrayList<String>(); concretePrototype.setHobbies(hobbies); System.out.println(concretePrototype); // 创建Client对象,准备开始克隆 Client client = new Client(concretePrototype); ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototype); System.out.println(concretePrototypeClone); System.out.println("克隆对象中的引用类型地址值:" + concretePrototypeClone.getHobbies()); System.out.println("原对象中的引用类型地址值:" + concretePrototype.getHobbies()); System.out.println("对象地址比较:"+(concretePrototypeClone.getHobbies() == concretePrototype.getHobbies())); } }
深克隆
例子:
public class Monkey { public int height; public int weight; public Date birthday; }
public class JinGuBang implements Serializable { public float h = 100; public float d = 10; public void big(){ this.d *= 2; this.h *= 2; } public void small(){ this.d /= 2; this.h /= 2; } }
public class QiTianDaSheng extends Monkey implements Cloneable,Serializable { public JinGuBang jinGuBang; public QiTianDaSheng(){ //只是初始化 this.birthday = new Date(); this.jinGuBang = new JinGuBang(); } @Override protected Object clone() throws CloneNotSupportedException { return this.deepClone(); } //深克隆 public Object deepClone(){ try{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); QiTianDaSheng copy = (QiTianDaSheng)ois.readObject(); copy.birthday = new Date(); return copy; }catch (Exception e){ e.printStackTrace(); return null; } } public QiTianDaSheng shallowClone(QiTianDaSheng target){ QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); qiTianDaSheng.height = target.height; qiTianDaSheng.weight = target.height; qiTianDaSheng.jinGuBang = target.jinGuBang; qiTianDaSheng.birthday = new Date(); return qiTianDaSheng; } //浅克隆 public QiTianDaSheng deep2(QiTianDaSheng target){ QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); qiTianDaSheng.height = target.height; qiTianDaSheng.weight = target.height; qiTianDaSheng.jinGuBang = target.jinGuBang; qiTianDaSheng.birthday = new Date(); return qiTianDaSheng; } }
public class DeepCloneTest { public static void main(String[] args) { QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); try { QiTianDaSheng clone = (QiTianDaSheng)qiTianDaSheng.clone(); System.out.println("深克隆:" + (qiTianDaSheng.jinGuBang == clone.jinGuBang)); } catch (Exception e) { e.printStackTrace(); } QiTianDaSheng q = new QiTianDaSheng(); QiTianDaSheng n = q.shallowClone(q); System.out.println("浅克隆:" + (q.jinGuBang == n.jinGuBang)); } }
深克隆破坏单例解决方式
要么你我们的单例类不实现Cloneable接口;
要么我们重写clone()方法,在clone方法中返回单例对象即可,具体代码如下:
@Override protected Object clone() throws CloneNotSupportedException{ return INSTANCE; }
Cloneable源码分析先看我们常用的ArrayList就实现了Cloneable接口,来看代码clone()方法的实现:`
public Object clone(){ try{ ArrayList<?>v=(ArrayList<?>) super.clone();v.elementData=Arrays.copyOf(elementData,size); v.modCount=0; return v; }catch(CloneNotSupportedExceptione){ 。。。 }
个人理解
感觉和之前new出来一个对象,再set值一样,只是,这个set的功能在对象内部。对外只暴露一个clone或者其他自定义接口。
原型克隆和new的区别
原型模式和抽象工厂模式的区别
本质
本质: 克隆生成对象。
代码地址:
https://github.com/hufanglei/pattern-learn/tree/master/src/main/java/com/example/prototype
笔记地址 https://blog.csdn.net/baidu_21349635/article/details/106086578