Prototype概述

Prototype - 图1

玩具代码案例 - 图形创建面板

原型产品角色

IGraphPrototype

  1. package online.javabook.gof.creational.patterns5.prototype.graph.palette.product;
  2. import java.io.IOException;
  3. public interface IGraphPrototype {
  4. public IGraphPrototype shallowClone() throws CloneNotSupportedException;
  5. public IGraphPrototype deepClone() throws IOException, ClassNotFoundException, CloneNotSupportedException;
  6. }

CircleGraphPrototype

在一个圆形图像类型的构造函数中存在一个较为缓慢的初始化过程,比如正在加载和解析配置文件资源。

  1. package online.javabook.design.gof.creational5.prototype.graph.palette.product;
  2. import java.awt.*;
  3. import java.io.*;
  4. public class CircleGraphPrototype implements IGraphPrototype, Serializable, Cloneable {
  5. private int size = 1;
  6. private int radius = 10;
  7. private String color = Color.BLACK.toString();
  8. public CircleGraphPrototype() throws InterruptedException {
  9. System.out.println(this.getClass().getSimpleName()+":开始初始化......");
  10. Thread.sleep(10000);
  11. System.out.println(this.getClass().getSimpleName()+":结束初始化......");
  12. }
  13. public int getRadius() {
  14. return radius;
  15. }
  16. public void setRadius(int radius) {
  17. this.radius = radius;
  18. }
  19. public int getSize() {
  20. return size;
  21. }
  22. public void setSize(int size) {
  23. this.size = size;
  24. }
  25. public String getColor() {
  26. return color;
  27. }
  28. public void setColor(String color) {
  29. this.color = color;
  30. }
  31. @Override
  32. public CircleGraphPrototype shallowClone() throws CloneNotSupportedException {
  33. return (CircleGraphPrototype) clone();
  34. }
  35. @Override
  36. public CircleGraphPrototype deepClone() throws IOException, ClassNotFoundException, CloneNotSupportedException {
  37. CircleGraphPrototype circle = (CircleGraphPrototype) clone();
  38. // out
  39. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  40. ObjectOutputStream oos = new ObjectOutputStream(bos);
  41. oos.writeObject(circle);
  42. // in
  43. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
  44. ObjectInputStream ois = new ObjectInputStream(bis);
  45. circle = (CircleGraphPrototype) ois.readObject();
  46. return circle;
  47. }
  48. }

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