原型模式
定义: 用于创建重复的对象,同时又能保证性能。用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
使用场景:
- 资源优化
- 性能和安全要求的场景
- 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
- 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用
- 原型模式很少单独出现,一般和工厂方法模式配合使用,原型模式 clone 对象,工厂方法提供调用
使用条件:
- 必须实现 Cloneable 接口。在 java 虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出 CloneNotSupportedException 异常。
- 重写 Object 类中的 clone() 方法
注意事项:
- 原型模式是通过拷贝一个现有对象生成新对象的,属于浅拷贝。只需要实现 Cloneable 接口,重写 Object 的 clone() 方法。深拷贝是通过实现 Serializable 读取二进制流。Object 类的 clone() 方法只会拷贝对象中的基本的数据类型,对于数组、对象等拷贝的是对象的地址(因此每个 clone 对象指向同一对象,无法做到数据隔离)。
- 原型模式复制对象不会调用类的构造方法。因为对象的复制是通过 Object 的 clone() 方法来完成的。因此,构造方法的访问权限也会失效,与单例模式也会发生冲突。
实现
原型类
/**
* 原型类
*/
@Data
public abstract class Prototype implements Cloneable{
protected String name;
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
public abstract void say(int i);
}
/**
* 原型类子类 1
*/
public class PrototypeSubclass1 extends Prototype{
public PrototypeSubclass1() {
name = "子类1 无参构造";
}
public PrototypeSubclass1(int i) {
name = "子类1 有参构造";
}
@Override
public void say(int i) {
System.out.println("创建了第 "+ i +" 个原型类子类1");
}
}
/**
* 原型类子类 2
*/
public class PrototypeSubclass2 extends Prototype{
public PrototypeSubclass2() {
name = "子类 2 无参构造";
}
public PrototypeSubclass2(int i) {
name = "子类 2 有参构造";
}
@Override
public void say(int i) {
System.out.println("创建了第 "+ i +" 个原型类子类2");
}
}
调用者(clone 对象)
public class CallPrototype {
public static void main(String[] args){
Prototype pt1 = new PrototypeSubclass1(1);
for(int i=0; i< 2; i++){
// clone 不会调用构造方法
Prototype prototype = (Prototype)pt1.clone();
prototype.say(i);
System.out.println(prototype.getName());
}
Prototype pt2 = new PrototypeSubclass2();
for(int i=0; i< 2; i++){
Prototype prototype = (Prototype)pt2.clone();
prototype.say(i);
System.out.println(prototype.getName());
}
}
}
------------------------打印结果-----------------------
创建了第 0 个原型类子类1
子类1 有参构造
创建了第 1 个原型类子类1
子类1 有参构造
创建了第 0 个原型类子类2
子类 2 无参构造
创建了第 1 个原型类子类2
子类 2 无参构造