Prototype概述
玩具代码案例 - 图形创建面板
原型产品角色
IGraphPrototype
package online.javabook.gof.creational.patterns5.prototype.graph.palette.product;
import java.io.IOException;
public interface IGraphPrototype {
public IGraphPrototype shallowClone() throws CloneNotSupportedException;
public IGraphPrototype deepClone() throws IOException, ClassNotFoundException, CloneNotSupportedException;
}
CircleGraphPrototype
在一个圆形图像类型的构造函数中存在一个较为缓慢的初始化过程,比如正在加载和解析配置文件资源。
package online.javabook.design.gof.creational5.prototype.graph.palette.product;
import java.awt.*;
import java.io.*;
public class CircleGraphPrototype implements IGraphPrototype, Serializable, Cloneable {
private int size = 1;
private int radius = 10;
private String color = Color.BLACK.toString();
public CircleGraphPrototype() throws InterruptedException {
System.out.println(this.getClass().getSimpleName()+":开始初始化......");
Thread.sleep(10000);
System.out.println(this.getClass().getSimpleName()+":结束初始化......");
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public CircleGraphPrototype shallowClone() throws CloneNotSupportedException {
return (CircleGraphPrototype) clone();
}
@Override
public CircleGraphPrototype deepClone() throws IOException, ClassNotFoundException, CloneNotSupportedException {
CircleGraphPrototype circle = (CircleGraphPrototype) clone();
// out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(circle);
// in
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
circle = (CircleGraphPrototype) ois.readObject();
return circle;
}
}
LineGraphPrototype
在一个线条图像类型的构造函数中存在一个较为缓慢的初始化过程,比如正在加载和解析配置文件资源。
package online.javabook.design.gof.creational5.prototype.graph.palette.product;
import java.awt.*;
import java.io.*;
public class LineGraphPrototype implements IGraphPrototype, Serializable, Cloneable {
private int size = 1;
private String color = Color.BLACK.toString();
public LineGraphPrototype() throws InterruptedException {
System.out.println(this.getClass().getSimpleName()+":开始初始化......");
Thread.sleep(10000);
System.out.println(this.getClass().getSimpleName()+":结束初始化......");
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public LineGraphPrototype shallowClone() throws CloneNotSupportedException {
return (LineGraphPrototype) clone();
}
@Override
public LineGraphPrototype deepClone() throws IOException, ClassNotFoundException, CloneNotSupportedException {
LineGraphPrototype line = (LineGraphPrototype) clone();
// out
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(line);
// in
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
line = (LineGraphPrototype) ois.readObject();
return line;
}
}
原型管理器角色
GraphPrototypeManager
原型管理器用来注册类型的原型对象。
package online.javabook.gof.creational.patterns5.prototype.graph.palette.manager;
import online.javabook.gof.creational.patterns5.prototype.graph.palette.product.IGraphPrototype;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class GraphPrototypeManager {
private Map<String, IGraphPrototype> graphPrototypeHashMap = new HashMap<>();
public void register(Class graphPrototypeClass, IGraphPrototype graphPrototype) {
graphPrototypeHashMap.put(graphPrototypeClass.getName(), graphPrototype);
}
public IGraphPrototype shallowClone(Class graphPrototypeClass) throws CloneNotSupportedException {
IGraphPrototype graphPrototype = graphPrototypeHashMap.get(graphPrototypeClass.getName());
return graphPrototype.shallowClone();
}
public IGraphPrototype deepClone(Class graphPrototypeClass) throws CloneNotSupportedException, IOException, ClassNotFoundException {
IGraphPrototype graphPrototype = graphPrototypeHashMap.get(graphPrototypeClass.getName());
return graphPrototype.deepClone();
}
}
不基于原型模式的实现
当我们不基于原型模式,同样的图形对象每次在实例化时都会非常缓慢,即便它们实例化后的内部状态都一样,或者在之后只会修改部分状态。例如在绘图板上创建出一个同样的图形,之后只不过就是改变一下它的位置,或者颜色,但是每次从图形工具面板拖拽它们到绘图区的时候就会出现卡顿。
Main
package online.javabook.design.gof.creational5.prototype.graph.palette.bad;
import online.javabook.design.gof.creational5.prototype.graph.palette.product.LineGraphPrototype;
public class Main {
public static void main(String[] args) throws InterruptedException {
LineGraphPrototype lineGraphPrototype1 = new LineGraphPrototype();
LineGraphPrototype lineGraphPrototype2 = new LineGraphPrototype();
System.out.println("lineGraphPrototype1:" +lineGraphPrototype1);
System.out.println("lineGraphPrototype2:" +lineGraphPrototype2);
}
}
Console
LineGraphPrototype:开始初始化......
LineGraphPrototype:结束初始化......
LineGraphPrototype:开始初始化......
LineGraphPrototype:结束初始化......
lineGraphPrototype1:online.javabook.design.gof.creational5.prototype.graph.palette.product.LineGraphPrototype@2d98a335
lineGraphPrototype2:online.javabook.design.gof.creational5.prototype.graph.palette.product.LineGraphPrototype@16b98e56
基于原型模式的实现
基于原型模式的思想,如果一个对象初始化后都是一样的,不如就在第一次创建的时候慢一次,之后将这个对象作为原型模版,复制出这样的对象就好了。因此无论深度复制也好,浅度复制也好,它们只是实现原型模式的技术手段,而并不是原型模式的目的。
Main
package online.javabook.design.gof.creational5.prototype.graph.palette.good;
import online.javabook.design.gof.creational5.prototype.graph.palette.manager.GraphPrototypeManager;
import online.javabook.design.gof.creational5.prototype.graph.palette.product.CircleGraphPrototype;
import online.javabook.design.gof.creational5.prototype.graph.palette.product.LineGraphPrototype;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException, InterruptedException {
// prototype manager
GraphPrototypeManager graphPrototypeManager = new GraphPrototypeManager();
// prototype register
LineGraphPrototype lineGraphPrototype = new LineGraphPrototype();
CircleGraphPrototype circleGraphPrototype = new CircleGraphPrototype();
graphPrototypeManager.register(LineGraphPrototype.class, lineGraphPrototype);
graphPrototypeManager.register(CircleGraphPrototype.class, circleGraphPrototype);
// shallow clone
System.out.println("shallow clone:");
LineGraphPrototype shallowCloneLineGraph = (LineGraphPrototype)graphPrototypeManager.shallowClone(LineGraphPrototype.class);
System.out.println("lineGraphPrototype:" +lineGraphPrototype);
System.out.println("shallowCloneLineGraph:" +shallowCloneLineGraph);
// deep clone
System.out.println("deep clone:");
CircleGraphPrototype deepCloneCircleGraph = (CircleGraphPrototype)graphPrototypeManager.deepClone(CircleGraphPrototype.class);
System.out.println("circleGraphPrototype:" +circleGraphPrototype);
System.out.println("deepCloneCircleGraph:" +deepCloneCircleGraph);
}
}
Console
这里可以看到,除了第一次创建原型实例的时候较慢,之后基于原型复制出新的实例的过程就非常快了。
LineGraphPrototype:开始初始化......
LineGraphPrototype:结束初始化......
CircleGraphPrototype:开始初始化......
CircleGraphPrototype:结束初始化......
shallow clone:
lineGraphPrototype:online.javabook.design.gof.creational5.prototype.graph.palette.product.LineGraphPrototype@2d98a335
shallowCloneLineGraph:online.javabook.design.gof.creational5.prototype.graph.palette.product.LineGraphPrototype@16b98e56
deep clone:
circleGraphPrototype:online.javabook.design.gof.creational5.prototype.graph.palette.product.CircleGraphPrototype@5e9f23b4
deepCloneCircleGraph:online.javabook.design.gof.creational5.prototype.graph.palette.product.CircleGraphPrototype@4783da3f