Prototype:原型模式
先代码
下面三组代码分别展示引用类型赋值、原型模式下“浅拷贝”、原型模式下“深拷贝”,便于代码可读,测试方法直接跟着类走了。
引用类型的赋值示例:
package h.l.demo.prototype;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月20日
* @Description: 引用类型的赋值示例
*/
public class Demo {
private String name;
private int age;
private char garde;
public Demo(String name, int age, char garde) {
super();
this.name = name;
this.age = age;
this.garde = garde;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public char getGarde() {
return garde;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setGarde(char garde) {
this.garde = garde;
}
@Override
public String toString() {
return "Demo [name=" + name + ", age=" + age + ", garde=" + garde
+ "]";
}
public static void main(String[] args) {
Demo p = new Demo("Is-Me-HL", 18, 'A');
System.out.println("p:" + p.toString());
System.out.println("-----------------------");
Demo p2 = p;
p2.setName("Is-Me-HL2");
p2.setAge(19);
p2.setGarde('B');
System.out.println("p2:" + p2.toString());
System.out.println("-----------------------");
System.out.println("p1==p2?"+(p==p2));
p2.setName("hehehehe");
System.out.println("p:" + p.toString());
System.out.println("p2:" + p2.toString());
}
}
运行结果:
原型模式下“浅拷贝”(通俗理解就是复制一个对象实例的所有成员,PS:不包括引用类型的成员):
package h.l.demo.prototype;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月20日
* @Description: 原型模式--浅拷贝示例
*/
public class Prototype implements Cloneable {
private String name;
private int age;
private char garde;
public Prototype(String name, int age, char garde) {
super();
this.name = name;
this.age = age;
this.garde = garde;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public char getGarde() {
return garde;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setGarde(char garde) {
this.garde = garde;
}
@Override
public String toString() {
return "Prototype [name=" + name + ", age=" + age + ", garde=" + garde
+ "]";
}
@Override
protected Object clone() {
Prototype p = null;
try {
p = (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
public static void main(String[] args) {
Prototype p = new Prototype("Is-Me-HL", 18, 'A');
System.out.println("p:" + p.toString());
System.out.println("-----------------------");
Prototype p2 = (Prototype) p.clone();
p2.setName("Is-Me-HL2");
p2.setAge(19);
p2.setGarde('B');
System.out.println("p2:" + p2.toString());
System.out.println("-----------------------");
System.out.println("p1==p2?"+(p==p2));
p2.setName("hehehehe");
System.out.println("p:" + p.toString());
System.out.println("p2:" + p2.toString());
}
}
运行结果:
原型模式下“深拷贝”(通俗理解就是基于浅拷贝,增加对对象实例中那些引用类型的拷贝):
package h.l.demo.prototype;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author: Is-Me-Hl
* @date: 2020年2月20日
* @Description: 原型模式-深拷贝示例
* 深拷贝和浅拷贝的区别就是:浅拷贝所能完全拷贝的对象是其属性中只包含基本类型,不包含引用类型。
* 深拷贝所拷贝的这个对象中的属性包含了引用类型(如对象、集合,ps:String为特殊的引用类型,不算在里面),
* 那么要完全拷贝这样的对象就要使用深拷贝对这样的引用类型的属性进行特殊处理,如下所示:
*/
public class CopyOfPrototype implements Cloneable {
private String name;
private int age;
private char garde;
// 下述两个属性使用需要进行深拷贝
// 处理方式,集合就在clone方法中添加一行克隆的语句,进行深拷贝。
// 注意的是集合顶层接口如List是没有clone方法的,所以属性的类型需要具体的子类,如下述使用的ArrayList
private ArrayList<String> list;
// 和CopyOfPrototype实现 Cloneable接口,重写自己的clone方法即可
private ClassDemo classDemo;
public CopyOfPrototype(String name, int age, char garde,
ArrayList<String> list, ClassDemo classDemo) {
super();
this.name = name;
this.age = age;
this.garde = garde;
this.list = list;
this.classDemo = classDemo;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public char getGarde() {
return garde;
}
public List<String> getList() {
return list;
}
public ClassDemo getClassDemo() {
return classDemo;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setGarde(char garde) {
this.garde = garde;
}
public void setList(ArrayList<String> list) {
this.list = list;
}
public void setClassDemo(ClassDemo classDemo) {
this.classDemo = classDemo;
}
@Override
public String toString() {
return "CopyOfPrototype [name=" + name + ", age=" + age + ", garde="
+ garde + ", list=" + list + ", classDemo=" + classDemo + "]";
}
@Override
protected Object clone() {
CopyOfPrototype p = null;
try {
p = (CopyOfPrototype) super.clone();
// 这里就是处理集合属性拷贝的语句。深拷贝
p.list = (ArrayList<String>) this.list.clone();
// 这里是处理对象拷贝的语句。深拷贝
p.classDemo = (ClassDemo) this.classDemo.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
public static void main(String[] args) {
ArrayList list = new ArrayList<String>();
list.add("UJS");
ClassDemo classDemo = new ClassDemo("HL");
CopyOfPrototype p = new CopyOfPrototype("Is-Me-HL", 18, 'A', list,
classDemo);
System.out.println("p:" + p.toString());
System.out.println("-----------------------");
CopyOfPrototype p2 = (CopyOfPrototype) p.clone();
p2.setName("Is-Me-HL2");
p2.setAge(19);
p2.setGarde('B');
System.out.println("p2:" + p2.toString());
System.out.println("-----------------------");
System.out.println("p1==p2?" + (p == p2));
p2.setName("JJJJJJJJ");
p2.getList().add("IOT");
p2.getClassDemo().setClassDemoName("HHHHHHHHHH");
p.getClassDemo().setClassDemoName("LLLLLLLLLL");
System.out.println("p:" + p.toString());
System.out.println("p2:" + p2.toString());
}
}
class ClassDemo implements Cloneable {
private String ClassDemoName;
public ClassDemo(String classDemoName) {
super();
ClassDemoName = classDemoName;
}
public String getClassDemoName() {
return ClassDemoName;
}
public void setClassDemoName(String classDemoName) {
ClassDemoName = classDemoName;
}
@Override
public String toString() {
return "ClassDemo [ClassDemoName=" + ClassDemoName + "]";
}
@Override
protected Object clone() {
ClassDemo p = null;
try {
p = (ClassDemo) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
运行结果:
后分析
- 个人建议:写代码是件幸福的事,So,do it
原型模式,用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道知道任何创建的细节。上述使用Java实现的原型模式代码示例。浅拷贝和深拷贝都是原型模式的应用,实现了cloneable这个标记接口,重写了clone方法,两者拷贝的范围略有差异罢了。原型对象的好处就是当初始信息不发生变化的情况下,克隆是最好的办法。这既隐藏了创建对象的细节,又对性能有了大大的提高,避免了没创建一个对象都new的情况,往往构造函数比较复制时,是很浪费资源的。
其他例子:参考自《大话设计模式》简历复印
注:以上文章仅是个人总结,若有不当之处,望不吝赐教