设计模式第五弹,原型模式
原型模式:通过使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。工作原理很简单,将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程。简单说就是clone。
需要注意的是通过clone方法创建的对象是全新的对象,在内存中有新的内存地址,通过对克隆对象进行的修改对原型对象是不会有影响的,每一个克隆对象都是互相独立的。
通用的克隆实现方法是在具体原型类的克隆方法中实例化一个与自身类型相同的对象并将其返回,并且将相关的参数传入新创建的对象中,保证他们的属性是相同的。
面向对象Java中的克隆方法满足:
- 对任何对象x,都有x.clone() != x,即克隆对象与原型对象不是同一个对象;
- 对任何对象x,都有x.clone().getClass() == x.getClass(),即克隆对象与原型对象的类型一样;
- 如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
深浅克隆的区别:
Java语言中,数据类型分为值类型和引用类型,值类型包括int , double , byte , boolean , char ,string等简单数据类型。引用类型包括类,接口,数组等复杂类型,深浅克隆的主要区别就是是否支持引用类型的成员变量的复制。
浅克隆: 在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。(值类型复制内存,引用类型复制地址引用)。
深克隆:在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。通过序列化(Serialization)实现。
原型管理器:简单来说就是模板的集合,将原型对象放入集合中,取出对象的时候不是把原型对象取出,二是原型对象的克隆对象。
练习:设计并实现一个客户类Customer,其中包含一个名为客户地址的成员变量,客户地址的类型为Address,用浅克隆和深克隆分别实现Customer对象的复制并比较这两种克隆方式的异同。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394//深克隆接口public interface DeepCloneable {Object deepClone() throws IOException, ClassNotFoundException;}public class Customer implements Cloneable, DeepCloneable ,Serializable{String name;int age;Adderss adderss;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Adderss getAdderss() {return adderss;}public void setAdderss(Adderss adderss) {this.adderss = adderss;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String toString() {return "Customer{" +"name='" + name + '\'' +", age=" + age +", adderss=" + adderss +'}';}public Customer clone() {Object object = null;try {object = super.clone();return (Customer) object;} catch (CloneNotSupportedException e) {System.out.println("不支持复制");return null;}}public Customer deepClone() throws IOException, ClassNotFoundException {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream oin = new ObjectInputStream(bin);return (Customer) oin.readObject();}}public class Adderss implements Serializable {String adderss;public String getAdderss() {return adderss;}public void setAdderss(String adderss) {this.adderss = adderss;}public String toString() {return "Adderss{" +"adderss='" + adderss + '\'' +'}';}}public static void main(String[] arg){Customer customer=new Customer();customer.setName("Tom");customer.setAge(15);Adderss adderss=new Adderss();adderss.setAdderss("北京");customer.setAdderss(adderss);Customer clone = customer.clone();Customer deepClone=null;try {deepClone = customer.deepClone();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}clone.setName("clone");clone.getAdderss().setAdderss("南京");deepClone.setName("deepClone");deepClone.getAdderss().setAdderss("东京");System.out.println(customer);System.out.println(clone);System.out.println(deepClone);}
运行结果: