原型模式简介
原型模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
原型模式的主要组成
- Prototype:抽象原型类。声明克隆自身的接口。
- ConcretePrototype:具体原型类。实现克隆的具体操作。
- Client:客户类。让一个原型克隆自身,从而获得一个新的对象。
实例模拟
原形类的编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class Person implements Cloneable {
private String head; private String body; private String foot;
public String getHead() { return head; }
public void setHead(String head) { this.head = head; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public String getFoot() { return foot; }
public void setFoot(String foot) { this.foot = foot; }
@Override public String toString() { return "Person{" + "head='" + head + '\'' + ", body='" + body + '\'' + ", foot='" + foot + '\'' + '}'; }
@Override protected Object clone() throws CloneNotSupportedException { try{ Person person = (Person) super.clone(); return person; }catch (CloneNotSupportedException e){ e.printStackTrace(); } return null; } }
|
客户端调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Client {
public static void main(String[] args) throws Exception { Person person = new Person(); person.setHead("头1"); person.setBody("身体1"); person.setFoot("脚1"); System.out.println(person.toString());
Person person2 = (Person)person.clone(); person2.clone(); System.out.println(person2.toString()); } }
|
结果如下

因为人有两个脚,此时如果我们把脚的属性改为集合会怎么样
1
| private List<String> foot = new ArrayList<>();
|
再次调用客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) throws Exception { Person person = new Person(); person.setHead("头1"); person.setBody("身体1"); person.getFoot().add("左脚一"); System.out.println("person1====="+person.toString());
Person person2 = (Person)person.clone(); person2.clone(); person2.getFoot().add("右脚一"); System.out.println("person2====="+person2.toString());
System.out.println("person1====="+person.toString()); }
|
此时我们发现再拷贝的对象属性发生改变以后原对象也会随之改变,这就是浅克隆,其引用数据类型数据还是还是指向原型对象的,并不会随之克隆
1 2 3
| person1=====Person{head='头1', body='身体1', foot=[左脚一]} person2=====Person{head='头1', body='身体1', foot=[左脚一, 右脚一]} person1=====Person{head='头1', body='身体1', foot=[左脚一, 右脚一]}
|