1、简介
指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
使用这种方式创建新的对象的话,就无需再通过 new 实例化来创建对象了。
在创建多个实例时,对创建过程的性能进行调优;
相对new来说,clone少了调用构造函数。如果构造函数中存在大量属性初始化或大对象,则使用clone的复制对象的方式性能会好一些。
-
优点:
- 性能提高。
- 逃避构造函数的约束。
-
缺点:
- 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
必须实现 Cloneable 接口。
-
使用场景:
- 资源优化场景。
- 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
- 性能和安全要求的场景。
- 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
- 一个对象多个修改者的场景。
- 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
- 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。
-
实际例子
- ArrayList等特别多
- ArrayList等特别多
2、示例
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
public class Prototype {
public static void main(String[] args) throws CloneNotSupportedException {
User user = new User();
user.setName("zhang");
user.setAge(0);
Address address = new Address();
address.setName("中国北京");
user.setAddress(address);
user.setPhone("111");
User clone = user.clone();
address.setName("中国上海");
System.out.println(user);
System.out.println(clone);
}
}
/**
* 必须实现Cloneable接口,同时接口只是起到一个标记作用
* 必须重写Object.clone方法
*/
@Data
class User implements Cloneable {
private String name;
private Integer age;
private Address Address;
private String phone;
/**
* 必须有的
*/
@Override
protected User clone() throws CloneNotSupportedException {
// 注意:浅拷贝,可变类型需要递归继续拷贝
// 底层二进制的方式进行copy 性能非常高
User user = (User) super.clone();
// 可以使使用fastJson或原生序列化方式深拷贝
User cloneUser = JSONObject.parseObject(JSONObject.toJSONString(user), User.class);
return cloneUser;
}
}
@Data
class Address{
private String name;
}