参考博文:https://www.cnblogs.com/java-my-life/archive/2012/04/11/2439387.html 用于自身学习,侵权必删。
2019-06-20 10:28:14
原型模式 Prototype
什么是原型模式:同样用于解决new对象的问题,类似于工厂模式中抽象产品和抽象工厂的合并。要求对象实现“克隆”自身的接口,通过复制对象本身来创建一个新的实例。
适用性:处理某些“结构复杂的对象”(某一复杂状态的对象)的创建工作。
原型模式的角色:
(1)Client:客户类提出创建对象的请求。
(2)Prototype:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。
(3)Concrete Prototype:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
基本类图:
克隆的两种概念:
浅克隆:只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。
深克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据。
两种克隆的实现方式:
1 浅克隆:实现Cloneable接口,调用Object对象的clone()方法,返回的便是浅克隆对象。
protected Object clone() throws CloneNotSupportedException
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式:x.clone() != x为 true,
表达式:x.clone().getClass() == x.getClass()也为 true,
但这些并非必须要满足的要求。一般情况下:x.clone().equals(x)为 true,但这并非必须要满足的要求。
2 深克隆:把对象写到流里的过程是序列化(Serialization)过程;而把对象从流中读出来的过程则叫反序列化(Deserialization)过程。
应当指出的是,写到流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。
序列化基本代码如下:
public Object deepClone() throws IOException, ClassNotFoundException{ //将对象写到流里 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); //从流里读回来 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); }
原型模式基本代码:
参看文首博文。
import java.io.*; public class Monkey implements Cloneable,Serializable{ public int age; public GoldRingedStaff staff; public Monkey(int age, GoldRingedStaff staff) { this.age = age; this.staff = staff; } public Monkey() { } //重写super.clone(),返回Mokey对象 @Override protected Monkey clone() throws CloneNotSupportedException { return (Monkey)super.clone(); } //深克隆 public Monkey 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); return (Monkey)ois.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("deep clone failed."); return null; } }
import java.io.Serializable; public class GoldRingedStaff implements Serializable { private float height = 100.0f; private float diameter = 10.0f; /** * 增长行为,每次调用长度和半径增加一倍 */ public void grow(){ this.diameter *= 2; this.height *= 2; } /** * 缩小行为,每次调用长度和半径减少一半 */ public void shrink(){ this.diameter /= 2; this.height /= 2; } }
public class TheGreatestSage { private Monkey monkey = new Monkey(10,new GoldRingedStaff()); public void change(){ try { Monkey copyMonkey = monkey.clone();//浅克隆 System.out.println("大圣本尊跟克隆的年龄是否相同 " + (monkey.age == copyMonkey.age)); System.out.println("大圣本尊跟克隆的大圣是否为同一个对象 " + (monkey == copyMonkey)); System.out.println("大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象" + (monkey.staff == copyMonkey.staff)); } catch (CloneNotSupportedException e) { e.printStackTrace(); System.out.println("clone failed"); } } public void deepChange(){ Monkey copyMonkey = monkey.deepClone(); System.out.println("大圣本尊跟克隆的年龄是否相同 " + (monkey.age == copyMonkey.age)); System.out.println("大圣本尊跟克隆的大圣是否为同一个对象 " + (monkey == copyMonkey)); System.out.println("大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象" + (monkey.staff == copyMonkey.staff)); } public static void main(String[] args) { TheGreatestSage sage = new TheGreatestSage(); sage.change(); System.out.println("========================"); sage.deepChange(); } }
//输出结果 大圣本尊跟克隆的年龄是否相同 true 大圣本尊跟克隆的大圣是否为同一个对象 false 大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象true ======================== 大圣本尊跟克隆的年龄是否相同 true 大圣本尊跟克隆的大圣是否为同一个对象 false 大圣本尊持有的金箍棒 跟 克隆的大圣持有的金箍棒是否为同一个对象false