原型模式

原型模式的定义如下:

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.

使用原型实例指定要创建的对象类型,并通过复制此原型来创建新对象。

还记得多莉吗?克隆羊!我们不讨论细节,但这里的关键点是这一切都与克隆有关。

用简单的话来说

通过克隆基于现有对象创建对象。

维基百科说

原型模式是软件开发中的一种创造性设计模式。当要创建的对象的类型由原型实例确定时使用,原型实例将被克隆以生成新的对象。

简而言之,它允许你创建一个现有对象的副本,并根据你的需要对其进行修改,而不是费尽周折地从头开始创建一个对象并进行设置。

原型模式的结构很简单:

  1. Prototype: 这个是一个接口,里面必须含有一个可以克隆自己的方法。在Java中,我们可以使用JDK自带的java.lang.Cloneable接口来替代此接口。
  2. ConcretePrototype:实现了Prototype接口的原型对象

原型模式主要用于对象的复制,它的核心是就是类图中的原型类 Prototype。Prototype 类需要具备以下两个条件:

  • 实现 Cloneable 接口。在 java 语言有一个 Cloneable 接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用 clone 方法。在 java 虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出 CloneNotSupportedException 异常。
  • 重写 Object 类中的 clone 方法。Java 中,所有类的父类都是 Object 类,Object 类中有一个 clone 方法,作用是返回对象的一个拷贝,但是其作用域 protected 类型的,一般的类无法调用,因此,Prototype 类需要将 clone 方法的作用域修改为 public 类型。

程序化示例:

第一步,Prototype抽象原型类,声明了copy方法,它可以是接口或基类

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class Prototype<T> implements Cloneable {

@SuppressWarnings({"unchecked"})
public Prototype<T> copy() {
try {
return (Prototype<T>) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}

}

第二步,原型类

这个类就是我们的原型类,准备被其他人克隆使用的,所以其实现Prototype 接口,具备克隆的能力。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
public class CloneSheep extends Prototype<CloneSheep> {

private String name;

private int age;

private String color;

public CloneSheep(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}

}

第三步,创建原型类的工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CloneSheepFactory {

private final CloneSheep cloneSheep;

public CloneSheepFactory(CloneSheep cloneSheep) {
this.cloneSheep = cloneSheep;
}

public CloneSheep createCloneSheep() {
return (CloneSheep) cloneSheep.copy();
}

}

测试:

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {

CloneSheepFactory sheepFactory = new CloneSheepFactory(new CloneSheep("多莉", 7, "白色"));
CloneSheep cloneSheep1 = sheepFactory.createCloneSheep();
CloneSheep cloneSheep2 = sheepFactory.createCloneSheep();
CloneSheep cloneSheep3 = sheepFactory.createCloneSheep();
System.out.println(cloneSheep1);
System.out.println(cloneSheep2);
System.out.println(cloneSheep3);

}

程序输出:

1
2
3
CloneSheep{name='多莉', age=7, color='白色'}
CloneSheep{name='多莉', age=7, color='白色'}
CloneSheep{name='多莉', age=7, color='白色'}

使用场景

  • 当一个对象的构建代价过高时。例如某个对象里面的数据需要访问数据库才能拿到,而我们却要多次构建这样的对象。
  • 当构建的多个对象,均需要处于某种原始状态时,就可以先构建一个拥有此状态的原型对象,其他对象基于原型对象来修改。

已知用途

  • java.lang.Object#clone()