设计模式-02原型模式

在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效,就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。

文章目录

  • 设计模式-02原型模式
    • 原型模式的定义与特点
    • 原型模式的结构与实现
      • 1. 模式的结构
      • 2. 模式的实现
    • 原型模式的应用实例
    • 原型模式的应用场景
    • 原型模式的扩展

原型模式的定义与特点

原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。在生活中复制的例子非常多,这里不一一列举了。
原型模式的优点:
● Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
● 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
原型模式的缺点:
● 需要为每一个类都配置一个 clone 方法
● clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
● 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。

原型模式的结构与实现

由于 Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单。

1. 模式的结构

原型模式包含以下主要角色。
1.抽象原型类:规定了具体原型对象必须实现的接口。
2.具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
3.访问类:使用具体原型类中的 clone() 方法来复制新的对象
其结构图如图 1 所示。

2. 模式的实现

原型模式的克隆分为浅克隆和深克隆。
● 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
● 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:

//具体原型类
class Realizetype implements Cloneable {Realizetype() {System.out.println("具体原型创建成功!");}public Object clone() throws CloneNotSupportedException {System.out.println("具体原型复制成功!");return (Realizetype) super.clone();}
}
//原型模式的测试类
public class PrototypeTest {public static void main(String[] args) throws CloneNotSupportedException {Realizetype obj1 = new Realizetype();Realizetype obj2 = (Realizetype) obj1.clone();System.out.println("obj1==obj2?" + (obj1 == obj2));}
}

程序的运行结果如下:

具体原型创建成功!
具体原型复制成功!
obj1==obj2?false //因为底层不是同一个对象

原型模式的应用实例

【例1】用原型模式模拟“孙悟空”复制自己。
分析:孙悟空拔下猴毛轻轻一吹就变出很多孙悟空,这实际上是用到了原型模式。这里的孙悟空类 SunWukong 是具体原型类,而 Java 中的 Cloneable 接口是抽象原型类。
同前面介绍的猪八戒实例一样,由于要显示孙悟空的图像,所以将孙悟空类定义成面板 JPanel 的子类,里面包含了标签,用于保存孙悟空的图像。
另外,重写了 Cloneable 接口的 clone() 方法,用于复制新的孙悟空。访问类可以通过调用孙悟空的 clone() 方法复制多个孙悟空,并在框架窗体 JFrame 中显示。图 2 所示是其结构图。

程序代码如下:

import java.awt.*;
import javax.swing.*;
class SunWukong extends JPanel implements Cloneable {private static final long serialVersionUID = 5543049531872119328L;public SunWukong() {JLabel l1 = new JLabel(new ImageIcon("src/Wukong.jpg"));this.add(l1);}public Object clone() {SunWukong w = null;try {w = (SunWukong) super.clone();} catch (CloneNotSupportedException e) {System.out.println("拷贝悟空失败!");}return w;}
}
public class ProtoTypeWukong {public static void main(String[] args) {JFrame jf = new JFrame("原型模式测试");jf.setLayout(new GridLayout(1, 2));Container contentPane = jf.getContentPane();SunWukong obj1 = new SunWukong();contentPane.add(obj1);SunWukong obj2 = (SunWukong) obj1.clone();contentPane.add(obj2);jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

程序的运行结果如图 3 所示。

用原型模式除了可以生成相同的对象,还可以生成相似的对象,请看以下实例。
【例2】用原型模式生成“三好学生”奖状。
分析:同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,属于相似对象的复制,同样可以用原型模式创建,然后再做简单修改就可以了。图 4 所示是三好学生奖状生成器的结构图。

程序代码如下:

public class ProtoTypeCitation {public static void main(String[] args) throws CloneNotSupportedException {citation obj1 = new citation("张三", "同学:在2016学年第一学期中表现优秀,被评为三好学生。", "韶关学院");obj1.display();citation obj2 = (citation) obj1.clone();obj2.setName("李四");obj2.display();}
}
//奖状类
class citation implements Cloneable {String name;String info;String college;citation(String name, String info, String college) {this.name = name;this.info = info;this.college = college;System.out.println("奖状创建成功!");}void setName(String name) {this.name = name;}String getName() {return (this.name);}void display() {System.out.println(name + info + college);}public Object clone() throws CloneNotSupportedException {System.out.println("奖状拷贝成功!");return (citation) super.clone();}
}

程序运行结果如下:

奖状创建成功!
张三同学:在2016学年第一学期中表现优秀,被评为三好学生。韶关学院
奖状拷贝成功!
李四同学:在2016学年第一学期中表现优秀,被评为三好学生。韶关学院

原型模式的应用场景

原型模式通常适用于以下场景。
● 对象之间相同或相似,即只是个别的几个属性不同的时候。
● 创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源。
● 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。
● 系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。

在 Spring 中,原型模式应用的非常广泛,例如 scope=‘prototype’、JSON.parseObject() 等都是原型模式的具体应用。

原型模式的扩展

原型模式可扩展为带原型管理器的原型模式,它在原型模式的基础上增加了一个原型管理器 PrototypeManager 类。该类用 HashMap 保存多个复制的原型,Client 类可以通过管理器的 get(String id) 方法从中获取复制的原型。其结构图如图 5 所示。

【例3】用带原型管理器的原型模式来生成包含“圆”和“正方形”等图形的原型,并计算其面积。分析:本实例中由于存在不同的图形类,例如,“圆”和“正方形”,它们计算面积的方法不一样,所以需要用一个原型管理器来管理它们,图 6 所示是其结构图。

程序代码如下:

import java.util.*;
interface Shape extends Cloneable {public Object clone();    //拷贝public void countArea();    //计算面积
}
class Circle implements Shape {public Object clone() {Circle w = null;try {w = (Circle) super.clone();} catch (CloneNotSupportedException e) {System.out.println("拷贝圆失败!");}return w;}public void countArea() {int r = 0;System.out.print("这是一个圆,请输入圆的半径:");Scanner input = new Scanner(System.in);r = input.nextInt();System.out.println("该圆的面积=" + 3.1415 * r * r + "\n");}
}
class Square implements Shape {public Object clone() {Square b = null;try {b = (Square) super.clone();} catch (CloneNotSupportedException e) {System.out.println("拷贝正方形失败!");}return b;}public void countArea() {int a = 0;System.out.print("这是一个正方形,请输入它的边长:");Scanner input = new Scanner(System.in);a = input.nextInt();System.out.println("该正方形的面积=" + a * a + "\n");}
}
class ProtoTypeManager {private HashMap<String, Shape> ht = new HashMap<String, Shape>();public ProtoTypeManager() {ht.put("Circle", new Circle());ht.put("Square", new Square());}public void addshape(String key, Shape obj) {ht.put(key, obj);}public Shape getShape(String key) {Shape temp = ht.get(key);return (Shape) temp.clone();}
}
public class ProtoTypeShape {public static void main(String[] args) {ProtoTypeManager pm = new ProtoTypeManager();Shape obj1 = (Circle) pm.getShape("Circle");obj1.countArea();Shape obj2 = (Shape) pm.getShape("Square");obj2.countArea();}
}

运行结果如下所示:

这是一个圆,请输入圆的半径:3
该圆的面积=28.2735这是一个正方形,请输入它的边长:3
该正方形的面积=9

设计模式-02原型模式相关推荐

  1. 【GOF23设计模式】原型模式

    [GOF23设计模式]原型模式 来源:http://www.bjsxt.com/  一.[GOF23设计模式]_原型模式.prototype.浅复制.深复制.Cloneable接口  浅复制 1 pa ...

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

    [索引页] [源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:webabcd 介绍 用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象. ...

  3. 教你如何一篇博客读懂设计模式之—--原型模式

    教你如何一篇博客读懂设计模式之----原型模式 what:是什么 原型模式: 用于创建重复的对象,既不用一个属性一个属性去set和get,又不影响性能,原型模式产生的对象和原有的对象不是同一个实例,他 ...

  4. 二十三种设计模式之原型模式

    今天继续探讨GOF二十三种设计模式的原型模式,原型模式也是属于创建型模式的一种 原型模式通俗的讲就是对象复制的过程,即通过一个原型对象,我可以得到一个该对象的克隆. 下面来看下原型模式的第一种写法-- ...

  5. C#设计模式(6)——原型模式(Prototype Pattern)

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...

  6. 设计模式回顾——原型模式(C++)

    文章目录 1 前言 2 什么是原型模式 2.1 原型模式组成 2.2 原型模式UML图 2.3 原型模式作用 3 原型模式优缺点 4 什么地方使用原型模式 5 原型模式实现 6 原型模式与构造函数 1 ...

  7. 设计模式之 原型模式

    原型模式应用场景举例:  GG和MM经常在QQ上聊天,但是GG打字的速度慢如蜗牛爬行,每次MM在瞬间完成恢复或者问候是,GG都会很紧张的去尽力快速打字,尽管如此,还是让MM有些不高心,MM说回复信息这 ...

  8. 设计模式之原型模式(Prototype)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式包括:1.FactoryMethod(工厂方法模式):2.Abstract Factory(抽象工厂模式):3.Sin ...

  9. golang设计模式之原型模式

    原型模式 wiki:原型模式是创建型模式的一种,其特点在于通过"复制"一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的"原型",这个 ...

  10. 【设计模式】原型模式 ( 概念简介 | 使用场景 | 优缺点 | 基本用法 )

    文章目录 I . 原型模式 概念简介 II . 原型模式 使用场景 III . 原型模式 优缺点 IV . 原型模式 实现及 简单示例 I . 原型模式 概念简介 原型模式 : 用原型实例指定创建对象 ...

最新文章

  1. Python量化库大全
  2. RESTful服务最佳实践
  3. 使用stm32的ADC得到准确的电压
  4. php图片上传报502,PHPStrom上传文件报502错误原因,_PHP教程
  5. instagram图片大小_一个开源的Instagram桌面照片上传器
  6. node.js删除文件
  7. 用qt的qml写的安卓摄像头程序
  8. 人人商城生成app教程_apicloud版人人商城app打包教程
  9. Visual Studio 2012安装教程
  10. 地震 matlab,MATLAB在地震信号处理中的应用实例.docx
  11. 树莓派linux负载均衡集群,在树莓派2上Nginx并发1W到底有多难
  12. 如何注册微信小程序的开发账号
  13. caption重要性 image_Multimodal —— 看图说话(Image Caption)任务的论文笔记(一)评价指标和NIC模型...
  14. 《心灵捕手》中的10段经典台词(10 classic lines from Good Will Hunting)
  15. Web 前端通过调用ActiveX实现LPT1端口小票机打印功能。
  16. Excel中使用名称定义常数
  17. 3 随机数与蒙特卡洛方法及Python实现
  18. 用计算机打青春不打烊,彩色的青春不打烊
  19. BOSS 业务运营支撑系统
  20. 三极管和MOS管的使用及区别

热门文章

  1. 我爱你各国的说法+50情话台词 拿去撩妹吧
  2. Groovy~Groovy运算符
  3. win7网络适配器_win7网络重置
  4. 求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。用scanf输入数据,输出计算结果
  5. Vue中Swiper以及vue-awesome-swiper的安装和问题
  6. 《看清你的思维图谱》读书笔记
  7. 计算机科学与技术用惠普星15,11代酷睿满血出击 快来GET蔡徐坤同款惠普星14吧...
  8. 家中买的计算机配置,配置,教您买电脑主要看哪些配置
  9. 过滤dt中重复的记录
  10. vue 使用iframe展示pdf文件