您的位置:首页 > 其它

【设计模式 - 4】之原型模式(Prototype)

2016-12-22 14:23 309 查看

1、模式简介

原型模式的定义:

  通过复制一个现有的对象(原型)来得到一个相似的对象。

原型模式的UML图如下图所示:



  从上图中可以看到,所有的对象实体类都是继承自一个Prototype的父类,而prototype类有一个可以复制对象的方法clone(),可以复制其任意子类。这样,所有Prototype类的子类在整个程序中只需要new一次,其他情况下只需要从这几个类中clone即可。

原型模式的适用场景:

当系统中需要重复的使用某一些类的对象时;

当这些对象的差别不是很大或完全相同时;

当一个类的对象必须在某几种状态之中时;

当系统需要对对象进行缓存时。

原型模式的优点:

克隆一般是在内存中以流的形式进行的,比创建一个对象速度快,因此原型模式可以提高系统的性能;

克隆对象的时候可以完全忽略类中的构造方法的访问权限,因此逃避构造函数的约束。

原型模式的缺点:

克隆并不是对所有的数据类型都适用,有些内部类(如ArrayList)是不支持克隆的;

克隆会忽略构造函数的约束,因此对于一些单例的类也会生成克隆对象,容易导致系统错误。

2、案例代码

需求:

  有三种形状圆形(Circle)、矩形(Rectangle)和三角形(Triangle)。多次调用这些形状排成一个队列集合。

分析:

  我们可以把这个题目中的几个逻辑想象成如下图所示的关系:



  我们让圆形(Circle)、矩形(Rectangle)和三角形(Triangle)三种图形继承Shape父类,然后在缓存ShapeCache类中的HashMap中分别缓存三种形状,当主函数中需要某种形状的时候,我们就从缓存中克隆一个使用。

说明:

  在JAVA中有一个Cloneable接口,是专门用来实现原型模式的。只需要让一个类实现这个接口,重写Object类的clone()方法,就可以方便的实现原型模式了。

代码:

1) 原型父类Shape:

public class Shape implements Cloneable {
protected String type;

@Override
protected Object clone() {
Shape shape = null;
try {
shape = (Shape) super.clone();
}catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return shape;
}

public void introduce() {
System.out.println("This is a " + type);
}
}


2) Shape的子类(以Circle类为例):

public class Circle extends Shape {

public Circle() {
super.type = "Circle";
}
}


3) 缓存类ShapeCache:

public class ShapeCache {
private Map<String, Shape> shapes;

public ShapeCache() {
loadCache();
}

private void loadCache() {
shapes = new HashMap<>();
shapes.put("circle", new Circle());
shapes.put("rectangle", new Rectangle());
shapes.put("triangle", new Triangle());
}

public Shape getShape(String id) {
Shape shape = shapes.get(id);
return (Shape) shape.clone();
}
}


4) 测试类Test:

public class Test {
public static void main(String[] args) {
List<Shape> shapeList = new ArrayList<>();

ShapeCachecache = new ShapeCache();
shapeList.add(cache.getShape("triangle"));
shapeList.add(cache.getShape("circle"));
shapeList.add(cache.getShape("rectangle"));
shapeList.add(cache.getShape("circle"));
shapeList.add(cache.getShape("rectangle"));
shapeList.add(cache.getShape("triangle"));
shapeList.add(cache.getShape("rectangle"));
shapeList.add(cache.getShape("circle"));

for (Shape shape : shapeList) {
shape.introduce();
}
}
}


5) 运行结果如下图所示:



3、扩展

  上面说过,JAVA中为我们提供了一个Cloneable接口,只有实现了这个接口之后,重写Object类中的clone()方法才有效,否则会报CloneNotSupportedException异常。

  使用原型模式复制对象时不会调用类的构造方法,因为复制出来的对象是原型对象复制粘贴出来的,是直接在内存中复制数据,因此不会调用到类的构造方法,甚至连访问权限都对原型模式无效,这一点在编程时需要特别注意。

  Object类的clone()方法只能拷贝对象中的8种基本数据类型,对于数组、容器、引用对象等都不会拷贝,这种现象被成为浅拷贝。与浅拷贝对应的是深拷贝,即在对对象进行浅拷贝之后,将对象中的数组、容器、引用对象单独进行拷贝。

  最后贴出原型模式的GitHub地址:【GitHub - Prototype】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: