原型模式,字面上的理解,以原型为标杆的模式。
原型模式其实就是从一个对象再创建另外一个可定制对象,而且不需知道任何创建的细节。
我们可以用原型示例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
Java里面一个比较典型的就是Cloneable接口,通过实现Cloneable接口,我们可以进行对象
的复制,这里当然就会讲到浅复制与深复制。
首先来看看原型模式的类图吧:
这里的Prototype是个基础的原型类,它实现了一个Cloneable的接口,也就是它能够把信息复制给另外一个类。
另外ConcretePrototype1和ConcretePrototype2继承自Prototype,因而也就有克隆功能,并且基于Prototype类
这个原型。
相关类图的代码就不贴了,这里主要给出Java中的深复制和浅复制的例子吧,便于理解。
PrototypeA类(用于浅复制):
package com.blog.anla.Prototype;
/**
* 原型类,声明一个克隆自身的接口 以浅复制为例
* @author U-ANLA
*
*/
public class PrototypeA implements Cloneable {
private int num1 = 0;
private int num2 = 0;
private People people;
public PrototypeA(){
people = new People();
}
@Override
protected Object clone() throws CloneNotSupportedException {
//并没有对people这个引用对象进行特殊处理
return (Object) super.clone();
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public People getPeople() {
return people;
}
public void setPeople(People people) {
this.people = people;
}
@Override
public String toString() {
return "PrototypeA [num1=" + num1 + ", num2=" + num2 + ", people="
+ people + "]";
}
}
PrototypeB类(用于测试深复制):
package com.blog.anla.Prototype;
/**
* 原型模式,以深复制为例
* @author U-ANLA
*
*/
public class PrototypeB {
private int num1 = 0;
private int num2 = 0;
private People people;
public PrototypeB(){
people = new People();
}
@Override
protected PrototypeB clone() throws CloneNotSupportedException {
//新创建了一个对象并返回
PrototypeB pb = new PrototypeB();
pb.num1 = this.num1;
pb.num2 = this.num2;
pb.people = pb.people;
return (PrototypeB)pb;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public People getPeople() {
return people;
}
public void setPeople(People people) {
this.people = people;
}
@Override
public String toString() {
return "PrototypeB [num1=" + num1 + ", num2=" + num2 + ", people="
+ people + "]";
}
}
辅助类People:
package com.blog.anla.Prototype;
/**
* 模板类,用来测试并区分浅复制和深复制。
* @author U-ANLA
*
*/
public class People {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People [name=" + name + ", age=" + age + "]";
}
public People(String name, int age) {
super();
this.name = name;
this.age = age;
}
public People() {
}
}
测试类Main:
package com.blog.anla.Prototype;
/**
* 测试的深复制浅复制类,很明显,两个输出不同
* 浅复制只会复制基本类型,而对于引用类型,则是直接给指向的应用
* 而深复制除了可以复制基本类型外,还能够复制一套引用类型变量。
* @author U-ANLA
*
*/
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
//浅复制
PrototypeA pa = new PrototypeA();
pa.setNum1(5);
pa.setNum2(6);
pa.getPeople().setAge(25);
pa.getPeople().setName("Jack");
PrototypeA pa1 = (PrototypeA)pa.clone();
//修改pa1的值而不修改pa2的相关值。
pa1.getPeople().setAge(23);
pa1.setNum1(4);
//对比结果
System.out.println(pa);
System.out.println(pa1);
/**
* 输出结果:
* PrototypeA [num1=5, num2=6, people=People [name=Jack, age=23]]
* PrototypeA [num1=4, num2=6, people=People [name=Jack, age=23]]
*/
System.out.println();
System.out.println();
//深复制
PrototypeB pb = new PrototypeB();
pb.setNum1(5);
pb.setNum2(6);
pb.getPeople().setAge(25);
pb.getPeople().setName("Jack");
PrototypeB pa2 = (PrototypeB)pb.clone();
//修改pa1的值而不修改pa2的相关值。
pa2.getPeople().setAge(23);
pa2.getPeople().setName("Tom");
pa2.setNum1(4);
//对比结果
System.out.println(pb);
System.out.println(pa2);
/**
* 输出结果:
* PrototypeB [num1=5, num2=6, people=People [name=Jack, age=25]]
* PrototypeB [num1=4, num2=6, people=People [name=Tom, age=23]]
*/
}
}
赠人玫瑰手留余香,希望有助于理解原型模式以及浅复制和深复制(oo)