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】

最新文章

  1. [ubuntu14.04 amd64 ]搜狗拼音輸入法安裝
  2. MATLAB代码加密生成.p文件
  3. IE8的Textarea滚动条乱跳的解决方案
  4. gitlab备份与恢复操作方法
  5. Poco库网络模块例子解析1-------字典查询
  6. Linux FTP的安装与配置(转)
  7. Android Studio 环境配置优化
  8. Eclipse开发android安装环境
  9. Ubuntu Linux 永山(mount)分
  10. 【SAP业务模式】之STO(一):业务背景和前台操作
  11. DSAPI TreeView节点增删简化操作
  12. fiddler模拟弱网测试点
  13. ThinkPHP 中使用 IS_AJAX 判断原生 JS 中的 Ajax 出现问题
  14. Java 虚拟机的垃圾回收
  15. vue之router钩子函数
  16. CURL错误代码及含义
  17. logstash 5.1.1 学习
  18. js转换数据格式为货币格式
  19. 解决sublime text 3中文乱码问题
  20. AIX安装CDE,CDE服务开启和关闭

热门文章

  1. php 连接mysql数据库并显示数据 实例 转载
  2. 对装饰模式(Decorator)的解读
  3. postman本地或远程访问不了
  4. ”ENV_IS_EMBEDDED“解惑以及相关的移植实验
  5. C# Dispose Finalize
  6. matlab读取指定路径下的图像
  7. 使用ListItem给DropDownList填充数据
  8. bzoj 1040: [ZJOI2008]骑士 環套樹DP
  9. 如何用 React Native 创建一个iOS APP?
  10. ThreadPoolExecutor介绍