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】

【设计模式 - 4】之原型模式(Prototype)的更多相关文章

  1. Net设计模式实例之原型模式( Prototype Pattern)

    一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...

  2. 设计模式系列之原型模式(Prototype Pattern)——对象的克隆

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  3. 设计模式学习心得<原型模式 Prototype >

    原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式是实现了一个原型接口,该接口用于创建当 ...

  4. IOS设计模式浅析之原型模式(Prototype)

    原型模式的定义 “使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象”.最初的定义出现于<设计模式>(Addison-Wesley,1994). 简单来理解就是根据这个原型创建 ...

  5. 《JAVA设计模式》之原型模式(Prototype)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述原型(Prototype)模式的: 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办 ...

  6. 设计模式入门之原型模式Prototype

    //原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象 //简单来说,当进行面向接口编程时,假设须要复制这一接口对象时.因为不知道他的详细类型并且不能实例化一个接口 //这时就须要 ...

  7. [工作中的设计模式]原型模式prototype

    一.模式解析 提起prototype,最近看多了js相关的内容,第一印象首先是js的原型 var Person=function(name){ this.name=name; } Person.pro ...

  8. 设计模式(四)原型模式Prototype(创建型)

      设计模式(四)原型模式Prototype(创建型) 1.   概述 我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象 ...

  9. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  10. PHP设计模式 原型模式(Prototype)

    定义 和工厂模式类似,用来创建对象.但实现机制不同,原型模式是先创建一个对象,采用clone的方式进行新对象的创建. 场景 大对象的创建. 优点 1.可以在运行时刻增加和删除产品 2.可以改变值或结构 ...

随机推荐

  1. 也谈Excel导出

    吐槽 Excel导出在天朝的软件大环境下,差点成为软件开发必备.俺就遇到过,所有报表不提供导出功能,就能不验收的囧事.报表能查看能打印能形成图表已经完美,实在搞不懂导出excel有个毛用,但是公司依靠 ...

  2. 一. 什么是ANR?为什么会有ANR发生?

    对于Android平台的工程师来说,ANR应该是每个人都会遇到的问题,因为导致它的原因有很多,例如在主线程进行耗时操作,调用大量cpu资源进行复杂的预算等,并且可能在大多数情况下,这类问题不会发生,只 ...

  3. Find your present (2) (位异或)

    Problem Description In the new year party, everybody will get a "special present".Now it's ...

  4. JSON字符串序列化与反序列化浅试

    一.添加引用(using Newtonsoft.Json.Linq;) 二. 1.生成json字符串源码 List<string> list = new List<string> ...

  5. C语言 rand()函数的用法

    rand()(产生随机数) 相关函数 srand() 表头文件 #include<stdlib.h> 定义函数 int rand()(void) 函数说明 rand()会返回一随机数值,范 ...

  6. tyvj 普通平衡树 SBT or splay

    普通平衡树 From admin     背景 Background 此为平衡树系列第一道:普通平衡树     描述 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中 ...

  7. Warm up 2

    hdu4619:http://acm.hdu.edu.cn/showproblem.php?pid=4619 题意:题目大意:给你两种纸牌 ,一种水平放置共有n张 ,一种竖直放置共有m张.水平放置的纸 ...

  8. 【POJ1284】Primitive Roots 欧拉函数

    题目描述: 题意: 定义原根:对于一个整数x,0<x<p,是一个mod p下的原根,当且仅当集合{ (xi mod p) | 1 <= i <= p-1 } 等于{ 1, .. ...

  9. 建立HttpsConnection

    1建立HttpConnection,这种连接比较简单,但是是不安全的,网上例子比较多,现在主要说说如果建立HttpsConnection,这种连接时通过SSL协议加密,相对更安全,一般使用这种连接传输 ...

  10. Android客户端调用Asp.net的WebService

    Android客户端调用Asp.net的WebService 我来说两句 |2011-11-23 13:39:15 在Android端为了与服务器端进行通信有几种方法:1.Socket通信2.WCF通 ...