设计模式——原型模式
一:基本介绍
原型模式是指:用原型实例创建对象的种类,并通过拷贝这些原型,创建新的对象。
二:问题案例
克隆羊问题:现有一只羊多利,年龄为1岁,颜色为白色,请编写程序创建和多利羊完全相同的10只羊。
1:传统解决方法
1 public class Client { 2 public static void main(String[] args) { 3 // TODO Auto-generated method stub 4 //传统的方法 5 Sheep sheep = new Sheep("tom", 1, "白色"); 6 7 Sheep sheep2 = new Sheep(sheep.getName(), 8 sheep.getAge(),sheep.getColor()); 9 Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); 10 Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); 11 12 Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor()); 13 //.... 14 15 System.out.println(sheep); 16 System.out.println(sheep2); 17 System.out.println(sheep3); 18 System.out.println(sheep4); 19 System.out.println(sheep5); 20 //... 21 }
分析:
在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂
总是需要重新初始化对象,而不是动态地获得对象运行时的状态, 不够灵活
2:使用原型模式解决
思路:
Java 中 Object 类是所有类的根类,Object 类提供了一个 clone()方法,该方法可以将一个 Java 对象复制一份, 但是需要实现 clone 的 Java 类必须要实现一个接口 Cloneable, 该接口表示该类能够复制且具有复制的能力 =>原型模式
Sheep实体类
1 public class Sheep implements Cloneable { 2 private String name; 3 private int age; 4 private String color; 5 private String address = "蒙古羊"; 6 public Sheep friend; //是对象, 克隆是会如何处理, 默认是浅拷贝 7 //get和set 8 //toString 9 //克隆该实例,使用默认的 clone 方法来完成 10 @Override 11 protected Object clone() { 12 Sheep sheep = null; 13 try { 14 sheep = (Sheep)super.clone(); 15 } catch (Exception e) { 16 System.out.println(e.getMessage()); 17 } 18 return sheep; 19 }
主方法
1 public static void main(String[] args) { 2 3 Sheep sheep = new Sheep("tom", 1, "白色"); 4 sheep.friend = new Sheep("jack", 2, "黑色"); 5 6 Sheep sheep2 = (Sheep)sheep.clone(); 7 Sheep sheep3 = (Sheep)sheep.clone(); 8 Sheep sheep4 = (Sheep)sheep.clone(); 9 Sheep sheep5 = (Sheep)sheep.clone(); 10 11 System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode()); 12 …… 13 }
三:对于深拷贝与浅拷贝
1:浅拷贝
1) 对于数据类型是基本数据类型的成员变量, 浅拷贝会直接进行值传递, 也就是将该属性值复制一份给新的对象。
2) 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值
3)浅拷贝是使用默认的 clone()方法来实现sheep = (Sheep) super.clone();所以前面的克隆羊就是浅拷贝
2:深拷贝
1)复制对象的所有基本数据类型的成员变量值
2)为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象(包括对象的引用类型 包括对象的引用类型)进行拷 进行拷贝
3)深拷贝实现方式
1:重写 clone 方法来实现深拷贝深拷贝实现方式
2:通过对象序列化 对象序列化实现深拷贝(推荐)