您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center 汽车系统工程   模型库  
会员   
   
嵌入式软件测试方法&实践
3月20日 线上
需求分析与管理
4月21-22日 北京+线上
SysML和EA进行系统设计建模
4月23-24日 北京+线上
     
   
 订阅
原型模式(原型设计模式)详解
 
  1858   次浏览      27 次
 2022-2-23
 
编辑推荐:
本文介绍原型模式的定义与特点,结构与实现以及原型模式的应用实例,原型模式的扩展,希望对您的学习有所帮助。
本文来自于语言中文网,由火龙果软件Alice编辑、推荐。

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

原型模式的定义与特点

原型(Prototype)模式 的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。在生活中复制的例子非常多,这里不一一列举了。

原型模式的优点:

  • Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
  • 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

原型模式的缺点:

  • 需要为每一个类都配置一个 clone 方法
  • clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
  • 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。

原型模式的结构与实现

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

1. 模式的结构

原型模式包含以下主要角色。

  1. 抽象原型类:规定了具体原型对象必须实现的接口。
  2. 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

其结构图如图 1 所示。

图1 原型模式的结构图

2. 模式的实现

原型模式的克隆分为 浅克隆 和 深克隆 。

  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:

  1. //具体原型类
  2. class Realizetype implements Cloneable {
  3. Realizetype () {
  4. System . out . println ( "具体原型创建成功!" );
  5. }
  6. public Object clone () throws CloneNotSupportedException {
  7. System . out . println ( "具体原型复制成功!" );
  8. return ( Realizetype ) super . clone ();
  9. }
  10. }
  11. //原型模式的测试类
  12. public class PrototypeTest {
  13. public static void main ( String [] args ) throws CloneNotSupportedException {
  14. Realizetype obj1 = new Realizetype ();
  15. Realizetype obj2 = ( Realizetype ) obj1 . clone ();
  16. System . out . println ( "obj1==obj2?" + ( obj1 == obj2 ));
  17. }
  18. }

程序的运行结果如下:
具体原型创建成功!
具体原型复制成功!
obj1==obj2?false

原型模式的应用实例

【例1】用原型模式模拟“孙悟空”复制自己。

分析:孙悟空拔下猴毛轻轻一吹就变出很多孙悟空,这实际上是用到了原型模式。这里的孙悟空类 SunWukong 是具体原型类,而 Java 中的 Cloneable 接口是抽象原型类。

同前面介绍的猪八戒实例一样,由于要显示孙悟空的图像( 点击此处下载该程序所要显示的孙悟空的图片 ),所以将孙悟空类定义成面板 JPanel 的子类,里面包含了标签,用于保存孙悟空的图像。

另外,重写了 Cloneable 接口的 clone() 方法,用于复制新的孙悟空。访问类可以通过调用孙悟空的 clone() 方法复制多个孙悟空,并在框架窗体 JFrame 中显示。图 2 所示是其结构图。

图2 孙悟空生成器的结构图

程序代码如下:
  1. import java . awt .*;
  2. import javax . swing .*;
  3. class SunWukong extends JPanel implements Cloneable {
  4. private static final long serialVersionUID = 5543049531872119328L ;
  5. public SunWukong () {
  6. JLabel l1 = new JLabel ( new ImageIcon ( "src/Wukong.jpg" ));
  7. this . add ( l1 );
  8. }
  9. public Object clone () {
  10. SunWukong w = null ;
  11. try {
  12. w = ( SunWukong ) super . clone ();
  13. } catch ( CloneNotSupportedException e ) {
  14. System . out . println ( "拷贝悟空失败!" );
  15. }
  16. return w ;
  17. }
  18. }
  19. public class ProtoTypeWukong {
  20. public static void main ( String [] args ) {
  21. JFrame jf = new JFrame ( "原型模式测试" );
  22. jf . setLayout ( new GridLayout ( 1 , 2 ));
  23. Container contentPane = jf . getContentPane ();
  24. SunWukong obj1 = new SunWukong ();
  25. contentPane . add ( obj1 );
  26. SunWukong obj2 = ( SunWukong ) obj1 . clone ();
  27. contentPane . add ( obj2 );
  28. jf . pack ();
  29. jf . setVisible ( true );
  30. jf . setDefaultCloseOperation ( JFrame . EXIT_ON_CLOSE );
  31. }
  32. }

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

图3 孙悟空克隆器的运行结果

用原型模式除了可以生成相同的对象,还可以生成相似的对象 ,请看以下实例。

【例2】用原型模式生成“三好学生”奖状。

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

图4 奖状生成器的结构图

程序代码如下:

  1. public class ProtoTypeCitation {
  2. public static void main ( String [] args ) throws CloneNotSupportedException {
  3. citation obj1 = new citation ( "张三" , "同学:在2016学年第一学期中表现优秀,被评为三好学生。" , "韶关学院" );
  4. obj1 . display ();
  5. citation obj2 = ( citation ) obj1 . clone ();
  6. obj2 . setName ( "李四" );
  7. obj2 . display ();
  8. }
  9. }
  10. //奖状类
  11. class citation implements Cloneable {
  12. String name ;
  13. String info ;
  14. String college ;
  15. citation ( String name , String info , String college ) {
  16. this . name = name ;
  17. this . info = info ;
  18. this . college = college ;
  19. System . out . println ( "奖状创建成功!" );
  20. }
  21. void setName ( String name ) {
  22. this . name = name ;
  23. }
  24. String getName () {
  25. return ( this . name );
  26. }
  27. void display () {
  28. System . out . println ( name + info + college );
  29. }
  30. public Object clone () throws CloneNotSupportedException {
  31. System . out . println ( "奖状拷贝成功!" );
  32. return ( citation ) super . clone ();
  33. }
  34. }

程序运行结果如下:
张三同学:在2016学年第一学期中表现优秀,被评为三好学生。
韶关学院 奖状拷贝成功!
李四同学:在2016学年第一学期中表现优秀,被评为三好学生。韶关学院

奖状创建成功!

原型模式的应用场景

原型模式通常适用于以下场景。

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

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

原型模式的扩展

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

图5 带原型管理器的原型模式的结构图

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

图6 图形生成器的结构图

程序代码如下:

  1. import java . util .*;
  2. interface Shape extends Cloneable {
  3. public Object clone (); //拷贝
  4. public void countArea (); //计算面积
  5. }
  6. class Circle implements Shape {
  7. public Object clone () {
  8. Circle w = null ;
  9. try {
  10. w = ( Circle ) super . clone ();
  11. } catch ( CloneNotSupportedException e ) {
  12. System . out . println ( "拷贝圆失败!" );
  13. }
  14. return w ;
  15. }
  16. public void countArea () {
  17. int r = 0 ;
  18. System . out . print ( "这是一个圆,请输入圆的半径:" );
  19. Scanner input = new Scanner ( System . in );
  20. r = input . nextInt ();
  21. System . out . println ( "该圆的面积=" + 3.1415 * r * r + " \n " );
  22. }
  23. }
  24. class Square implements Shape {
  25. public Object clone () {
  26. Square b = null ;
  27. try {
  28. b = ( Square ) super . clone ();
  29. } catch ( CloneNotSupportedException e ) {
  30. System . out . println ( "拷贝正方形失败!" );
  31. }
  32. return b ;
  33. }
  34. public void countArea () {
  35. int a = 0 ;
  36. System . out . print ( "这是一个正方形,请输入它的边长:" );
  37. Scanner input = new Scanner ( System . in );
  38. a = input . nextInt ();
  39. System . out . println ( "该正方形的面积=" + a * a + " \n " );
  40. }
  41. }
  42. class ProtoTypeManager {
  43. private HashMap<String, Shape> ht = new HashMap < String , Shape >();
  44. public ProtoTypeManager () {
  45. ht . put ( "Circle" , new Circle ());
  46. ht . put ( "Square" , new Square ());
  47. }
  48. public void addshape ( String key , Shape obj ) {
  49. ht . put ( key , obj );
  50. }
  51. public Shape getShape ( String key ) {
  52. Shape temp = ht . get ( key );
  53. return ( Shape ) temp . clone ();
  54. }
  55. }
  56. public class ProtoTypeShape {
  57. public static void main ( String [] args ) {
  58. ProtoTypeManager pm = new ProtoTypeManager ();
  59. Shape obj1 = ( Circle ) pm . getShape ( "Circle" );
  60. obj1 . countArea ();
  61. Shape obj2 = ( Shape ) pm . getShape ( "Square" );
  62. obj2 . countArea ();
  63. }
  64. }

运行结果如下所示:

这是一个圆,请输入圆的半径:3

该圆的面积=28.2735

这是一个正方形,请输入它的边长:3

该正方形的面积=9

   
1858   次浏览       27 次
相关文章

领域知识与限界上下文
深度解析DDD中台和微服务设计
领域建模的体系化思维与6种方法论
迄今为止最完整的DDD实践
 
相关文档

设计模式-原型模式
设计模式.组合模式
设计模式的六大原则实例
设计模式和代码重构
相关课程

JavaEE架构、 设计模式及性能调优
高质量软件设计与设计模式
设计模式及最佳实践
J2EE设计模式指南

最新活动计划
嵌入式软件测试方法&实践 3-20[在线]
MBSE理论方法到工作实践 3-28[北京]
需求分析与管理 4-21[在线]
基于LLM的Agent应用开发 4-18[北京]
SysML和EA系统设计建模 4-23[北京]
基于本体的体系架构设计 4-24[北京]
认证课:OCSMP-MU 周末班[在线]
 
 
最新文章
SysML图解
UAF 过程指南
代码逆向模型:QT插件Demo
基于企业架构的企业数字化指南
采用SysML对FPGA逻辑单元进行建模
DoDAF建模图例(EA+UPDM)
硬件模型:智驾域控制器(建模工具EA)
UML建模指南(建模工具iSpace)
更多...   
MBSE工具
MBSE平台
建模工具 EA
模型库-Model Center
需求管理-ReqManager
自动建模-Modeler
多级仿真-Sys Simulator
代码工程-Code Engineer
文档生成器-DocGenerator
更多...   
成功案例
某汽车整车企业 MBSE工具链和咨询服务
航天三院某研究所 建模工具、模型库和咨询
零跑汽车 建模工具EA及服务
赛力斯 MBSE工具链和培训服务
高合汽车研发部门 建模工具EA、WebEA、
广汽研究院 SysML+EA+软件分析设计
高合汽车研发部门 建模工具EA、WebEA、
国汽智联 建模工具EA、模型库、WebEA
更多...