原型模式
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
1、使用方法
- 实现Cloneable接口
- 重写clone方法
其中clone()是一个本地方法
protected native Object clone() throws CloneNotSupportedException;
2、浅克隆
-
新建一个pojo类:User.java
package pers.mobian.prototype.demo1; import java.util.Date; /* * 1.实现Cloneable接口 * 2.重写clone方法 * */ public class User implements Cloneable{ private String name; private Date createTime; @Override protected Object clone() throws CloneNotSupportedException { //protected native Object clone()调用了本地方法 return super.clone(); } public User() { } public User(String name, Date createTime) { this.name = name; this.createTime = createTime; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", createTime=" + createTime + '}'; } }
-
新建一个测试类:People.java
package pers.mobian.prototype.demo1; import java.util.Date; public class People { public static void main(String[] args) throws CloneNotSupportedException { Date date = new Date(); User user = new User("默辨", date); //使用clone()方法,达到克隆对象的效果 User user2 = (User) user.clone(); //打印原始对象以及被克隆的对象 System.out.println(user.toString()); System.out.println(user.hashCode()); System.out.println("---------"); System.out.println(user2.toString()); System.out.println(user2.hashCode()); System.out.println("============="); //重新设置创建对象的时间和名字 date.setTime(111); user.setName("mobian"); //打印重新设置创建时间以后的对象 System.out.println(user.toString()); System.out.println(user.hashCode()); System.out.println("---------"); System.out.println(user2.toString()); System.out.println(user2.hashCode()); } }
-
测试结果
User{name='默辨', createTime=Sat Mar 07 10:05:39 CST 2020} 787867107 --------- User{name='默辨', createTime=Sat Mar 07 10:05:39 CST 2020} 57494364 ============= User{name='mobian', createTime=Thu Jan 01 08:00:00 CST 1970} 787867107 --------- User{name='默辨', createTime=Thu Jan 01 08:00:00 CST 1970} 57494364
总结:我们会发现,user2和user的哈希值不一样,并且重新设置的name属性也发生了变化,即克隆成功。但是当我们重新设置了原始对象user的创建时间以后,被克隆的对象user2创建时间也发生了改变。即依然存在时间的引用。这种克隆方式成为浅克隆。即基本变量克隆成功,引用变量克隆不成功。
3、深克隆
由于我们希望引用变量也能够被克隆,所以我们引入了深克隆。于是我们对之前代码中的clone()方法进行改造,使其达到深克隆的效果。
-
改造User类的clone()方法
package pers.mobian.prototype.demo1; import java.util.Date; public class User implements Cloneable{ private String name; private Date createTime; @Override protected Object clone() throws CloneNotSupportedException { //1.将克隆的对象用obj类来接收 Object obj = super.clone(); //2.将obj对象强转为User类型 User user = (User) obj; //3.将最初克隆的时间,直接赋值给克隆对象的时间,使其能够达到强行改变的效果 user.createTime = (Date)this.getCreateTime().clone(); //4.返回被改造以后的对象 return obj; } public User() { } public User(String name, Date createTime) { this.name = name; this.createTime = createTime; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", createTime=" + createTime + '}'; } }
-
测试类不变
package pers.mobian.prototype.demo1; import java.util.Date; public class People { public static void main(String[] args) throws CloneNotSupportedException { Date date = new Date(); User user = new User("默辨", date); //使用clone()方法,达到克隆对象的效果 User user2 = (User) user.clone(); //打印原始对象以及被克隆的对象 System.out.println(user.toString()); System.out.println(user.hashCode()); System.out.println("---------"); System.out.println(user2.toString()); System.out.println(user2.hashCode()); System.out.println("============="); //重新设置创建对象的时间 date.setTime(111); user.setName("mobian"); //打印重新设置创建时间以后的对象 System.out.println(user.toString()); System.out.println(user.hashCode()); System.out.println("---------"); System.out.println(user2.toString()); System.out.println(user2.hashCode()); } }
-
测试结果
User{name='默辨', createTime=Sat Mar 07 10:21:17 CST 2020} 787867107 --------- User{name='默辨', createTime=Sat Mar 07 10:21:17 CST 2020} 57494364 ============= User{name='mobian', createTime=Thu Jan 01 08:00:00 CST 1970} 787867107 --------- User{name='默辨', createTime=Sat Mar 07 10:21:17 CST 2020} 57494364
总结:此时的效果不仅克隆了基本类型变量,并且成功的克隆到了引用类型的变量。此时的克隆称为深克隆。当然,深克隆的方法还有使用序列化和反序列化,不过能力有限,请前往其他地方查看。