1. 什么是原型模式
原型模式是一个创建型的模式,它实现了一个原型接口,这个接口用于创建当前对象的克隆。当直接创建对象的代价很大时,很适合采用这种方式。
在执行Object类的clone()方法时,此类必须要实现Cloneable接口,这个接口没有任何方法。
public interface Cloneable {
}
它只是告诉jvm,这个类可以执行clone()方法。
如果没有实现这个接口,则会提示CloneNotSupportedException.
2. 适用场景
原型模式是利用对象克隆来实现的。使用克隆能节约大量的资源。利用克隆技术,可以拷贝对象的复制,而不影响原对象。
- a.通过new生成一个对象需要繁琐的数据准备或权限时
- b.一个对象需要在高代价的数据库操作后才能被创建时,可以缓存这个对象,在下一个请求时,返回它的克隆,在需要的时候更新数据库,以减少数据库的调用。
- c.一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
3. 浅克隆与深克隆
浅克隆
java默认对基本数据类型进行值的克隆,对数组,集合,对象的引用等都还是引用的之前的地址。被复制的所有变量都含有和原来对象相同的值,只是复制对象,而不复制,它所引用的对象。
深克隆
需要手动的进行克隆代码的编写。把要复制的所引用的对象都复制了一遍。
4. 示例demo
用户类(浅克隆)
public class User implements Cloneable{
private String name;
private String age;
private String sex;
private String[] array;
private Role role;
public User(Role role){
this.role = role;
}
public User(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
@Override
protected User clone() throws CloneNotSupportedException {
// 浅克隆
User temp = (User) super.clone();
return temp;
}
}
角色类
public class Role implements Cloneable{
private String roleName = "默认角色";
private String memo = "默认备注";
private String auth = "默认权限";
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
public String getAuth() {
return auth;
}
public void setAuth(String auth) {
this.auth = auth;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类
public static void main(String[] args) throws CloneNotSupportedException {
User user = new User(new Role());
user.setArray(new String[]{"1"});
User cloneUser = user.clone();
System.out.println(user.getName() == cloneUser.getName());
System.out.println(user.getRole() == cloneUser.getRole());
System.out.println(user.getArray() == cloneUser.getArray());
}
浅克隆时运行结果
true
true
true
深克隆,修改用户类中的clone()方法
@Override
protected User clone() throws CloneNotSupportedException {
// 深克隆
User temp = (User) super.clone();
temp.role = (Role) this.role.clone();
temp.array = this.array.clone();
return temp;
}
深克隆时的运行结果:
true
false
false
注意到这里的role和array 在深克隆前后,在==时返回false,说明引用的不是同一个对象。
5. 总结
原型模式优点:
a.对象是通过clone方法生成,不是通过new 生成,节省了资源,提高了效率。
b.在多线程环境下,需要生成同一个类的多个对象的时候,不会产生并发等问题。
c.逃避构造函数的约束,直接在内存中拷贝,不会执行构造方法。
原型模式缺点:
a.每个原型都要实现Cloneable接口,复写clone()方法
b.如果是对之前的代码进行改造,则会是一种侵入式改造,违背了“开闭”原则