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. javascript 中的数据驱动页面模式

    前段时间一直在想前端MVC的意义.这个话题仁者见仁,但是MVC的使用方法给我提了一个管理数据的有意思的想法--数据管理和数据驱动页面.我们以前的思路一直是事件驱动页面,事件驱动页面合乎逻辑而且节约代码 ...

  2. 《Velocity 模板使用指南》中文版[转]

    转自:http://blog.csdn.net/javafound/archive/2007/05/14/1607931.aspx <Velocity 模板使用指南>中文版 源文见 htt ...

  3. [转]显示文件命令:cat、more、less、tail、touch详解

    cat命令cat命令连接文件并打印到标准输出设备上.cat经常用来显示文件的内容,类似于下的type命令. 一般格式:cat [选项] 文件说明:该命令有两项功能,其一是用来显示文件的内容,它依次读取 ...

  4. windows 基础及基本软件测试环境搭建

  5. C# 数据结构 线性表(顺序表 链表 IList 数组)

    线性表 线性表是最简单.最基本.最常用的数据结构.数据元素 1 对 1的关系,这种关系是位置关系. 特点 (1)第一个元素和最后一个元素前后是没有数据元素,线性表中剩下的元素是近邻的,前后都有元素. ...

  6. 简单学c——前言

      1.学C语言需要什么基础吗? 零基础. 2.什么是C语言? C语言是一种编程语言. 3.什么是编程语言? 编程语言是用来定义计算机程序的形式语言,是一种被标准化的交流技巧,用来向计算机发出指令. ...

  7. 学习总结之Log4NET

    通过在网上查找了一些资料,用了些时间学习了log4NET,做了一个小小的总结,说一下它的特点吧 首先呢log4NET是.Net下一个非常优秀的开源日志记录组件.它可以将日志分成不同等级,也可以按照我们 ...

  8. winform下载网页源码

    public partial class Form1 : Form{public Form1(){InitializeComponent();} private void button1_Click( ...

  9. LightOj_1079 Just another Robbery

    题目链接 题意: 抢银行(这个背景最爱了), 有n家银行, 每家银行抢劫被抓的概率是p[i],你认为当你被抓的概率低于P的时候是安全的. 问, 你最多能抢劫到多少money. 思路: 抽象成背包问题, ...

  10. clang: error: invalid deployment target for -stdlib=libc++ (requires iOS 5.0 or later)

    低于5.0版本的不支持设置成 或 在Xcode中做如下配置 静态库工程也要做同样设置