原型模式
1. 概念
原型模式是指创建新对象的时候,根据现有的一个原型来创建。原型模式用于创建重复的对象,同时又能保证性能。
原型模式提供了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,通常采用这种所谓的原型模式——例如,一个对象需要在一个高代价的数据库操作之后被创建,此时我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,从而减少数据库调用。
实现原型模式时,需要实现克隆操作——在 JAVA 中即继承 Cloneable
,重写 clone()
。
应用场景:
- 资源优化场景——如,类初始化时需要消化非常多的资源,包括数据、硬件资源等。
- 性能和安全要求的场景——通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
- 一个对象多个修改者的场景——一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现——通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,可以随手拿来使用。
2. 示例
我们将创建一个抽象类 Shape
和扩展了 Shape
类的实体类,然后定义类 ShapeCache
,该类把 shape
对象存储在一个 Hashtable
中,并在收到请求的时候返回 shape
对象的克隆。我们以客户端类 PrototypePatternDemo
使用 ShapeCache
类来获取 Shape
对象。

创建一个实现了
Cloneable
接口的抽象类public abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } }
创建扩展了上面抽象类的实体类
public class Rectangle extends Shape { public Rectangle(){ type = "Rectangle"; } @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
public class Square extends Shape { public Square(){ type = "Square"; } @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
public class Circle extends Shape { public Circle(){ type = "Circle"; } @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
创建一个类,从数据库获取实体类,并把它们存储在一个
Hashtable
中import java.util.Hashtable; public class ShapeCache { private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } // 对每种形状都运行数据库查询,并创建该形状 // shapeMap.put(shapeKey, shape); // 例如,我们要添加三种形状 public static void loadCache() { Circle circle = new Circle(); circle.setId("1"); shapeMap.put(circle.getId(),circle); Square square = new Square(); square.setId("2"); shapeMap.put(square.getId(),square); Rectangle rectangle = new Rectangle(); rectangle.setId("3"); shapeMap.put(rectangle.getId(),rectangle); } }
PrototypePatternDemo
使用ShapeCache
类来获取存储在Hashtable
中的形状的克隆public class PrototypePatternDemo { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape = (Shape) ShapeCache.getShape("1"); System.out.println("Shape : " + clonedShape.getType()); Shape clonedShape2 = (Shape) ShapeCache.getShape("2"); System.out.println("Shape : " + clonedShape2.getType()); Shape clonedShape3 = (Shape) ShapeCache.getShape("3"); System.out.println("Shape : " + clonedShape3.getType()); } }
// 执行程序,输出结果: Shape : Circle Shape : Square Shape : Rectangle