第六章 Caché 设计模式 原型模式

Posted 技术理科直男

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第六章 Caché 设计模式 原型模式相关的知识,希望对你有一定的参考价值。

第六章 Caché 设计模式 原型模式

定义

  • 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

  • 原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。

使用场景

使用原形模式可以解决复杂对象构建资源消耗的问题。也可以用来只读保护。注意其java里继承Cloneable接口。C#继承ICloneable接口。Caché 直接使用%ConstructClone()方法,克隆时不会走构造函数。

优点

  • 一般在初始化的信息不发生变的情况下,克隆是最好的办法,这即隐藏了对象创建的细节,又对性能是大大的提高。

  • 不用重新初始化对象,而是动态地获得对象运行时的状态。

结构图

描述

要求有一个简历类,必须要有姓名,可以设置性别和年龄,可以设置工作经历。最终需要三分简历。

示例

简历类

 
   
   
 
  1. Class PHA.YX.Design.Prototype.Resume Extends %RegisteredObject

  2. {


  3. Property name As %String [ Private ];


  4. Property sex As %String [ Private ];


  5. Property age As %String [ Private ];


  6. Property timeArea As %String [ Private ];


  7. Property company As %String [ Private ];



  8. Method %OnNew(name As %String) As %Status [ Private, ServerOnly = 1 ]

  9. {

  10. s $this.name = name

  11. Quit $$$OK

  12. }


  13. Method SetPersonalInfo(sex As %String, age As %String)

  14. {

  15. s $this.sex=sex

  16. s $this.age=age

  17. }


  18. Method SetWorkExperience(timeArea As %String, company As %String)

  19. {

  20. s $this.timeArea=timeArea

  21. s $this.company=company

  22. }


  23. Method Display()

  24. {

  25. w ..name _ " " _ ..sex _ " " _ ..age,!

  26. w "工作经历:" _ ..timeArea _ " " _ ..company,!

  27. }


  28. }

初级写法

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExamplePrimary()

  2. ClassMethod PrototypeExamplePrimary()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  7. s mResumeB = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  8. d mResumeB.SetPersonalInfo("男","30")

  9. d mResumeB.SetWorkExperience("2015-2020","XX公司")


  10. s mResumeC = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  11. d mResumeC.SetPersonalInfo("男","30")

  12. d mResumeC.SetWorkExperience("2015-2020","XX公司")


  13. d mResumeA.Display()

  14. d mResumeB.Display()

  15. d mResumeC.Display()

  16. }

 
   
   
 
  1. DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExamplePrimary()

  2. 姚鑫 30

  3. 工作经历:2015-2020 XX公司

  4. 姚鑫 30

  5. 工作经历:2015-2020 XX公司

  6. 姚鑫 30

  7. 工作经历:2015-2020 XX公司

缺点

三分简历需要实例化三次,如果需要一百份,就需要实例化一百次,徒增内存。

中级写法

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()

  2. ClassMethod PrototypeExampleIntermediate()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  7. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  8. s mResumeB = mResumeA


  9. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  10. s mResumeC = mResumeA


  11. d mResumeA.Display()

  12. d mResumeB.Display()

  13. d mResumeC.Display()

  14. }

 
   
   
 
  1. DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()

  2. 姚鑫 30

  3. 工作经历:2015-2020 XX公司

  4. 姚鑫 30

  5. 工作经历:2015-2020 XX公司

  6. 姚鑫 30

  7. 工作经历:2015-2020 XX公司

缺点

引用传值,改动其中一处其他复制实例一起改动。把mResumeB设置一下年龄,mResumeC设置一下公司。如下:

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()

  2. ClassMethod PrototypeExampleIntermediate()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  7. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  8. s mResumeB = mResumeA

  9. d mResumeB.SetPersonalInfo("男","31")


  10. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  11. s mResumeC = mResumeA

  12. d mResumeC.SetWorkExperience("2017-2020","SS公司")

  13. d mResumeA.Display()

  14. d mResumeB.Display()

  15. d mResumeC.Display()

  16. }

运行结果

 
   
   
 
  1. DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()

  2. 姚鑫 31

  3. 工作经历:2017-2020 SS公司

  4. 姚鑫 31

  5. 工作经历:2017-2020 SS公司

  6. 姚鑫 31

  7. 工作经历:2017-2020 SS公司

高级写法 (浅复制)

使用 .%ConstructClone()方法复制

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExampleSenior()

  2. ClassMethod PrototypeExampleSenior()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  7. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  8. s mResumeB = mResumeA.%ConstructClone()

  9. d mResumeB.SetPersonalInfo("男","31")


  10. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  11. s mResumeC =mResumeA.%ConstructClone()

  12. d mResumeC.SetWorkExperience("2017-2020","SS公司")


  13. d mResumeA.Display()

  14. d mResumeB.Display()

  15. d mResumeC.Display()

  16. }

 
   
   
 
  1. DHC-APP> d ##class(PHA.YX.Design.Program).PrototypeExampleSenior()

  2. 姚鑫 30

  3. 工作经历:2015-2020 XX公司

  4. 姚鑫 31

  5. 工作经历:2015-2020 XX公司

  6. 姚鑫 30

  7. 工作经历:2017-2020 SS公司

浅复制

如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象,因此原始对象及其副本引用统一对象。如下增加一个工作经验类的引用字段:

增加一个WorkExperience类

 
   
   
 
  1. Class PHA.YX.Design.Prototype.WorkExperience Extends %RegisteredObject

  2. {


  3. Property workDate As %String [ Private ];


  4. Method workDateGet() As %String [ ServerOnly = 1 ]

  5. {

  6. Quit i%workDate

  7. }


  8. Method workDateSet(Arg As %String) As %Status [ ServerOnly = 1 ]

  9. {

  10. s i%workDate = Arg

  11. Quit $$$OK

  12. }


  13. Property company As %String [ Private ];


  14. Method companyGet() As %String [ ServerOnly = 1 ]

  15. {

  16. Quit i%company

  17. }


  18. Method companySet(Arg As %String) As %Status [ ServerOnly = 1 ]

  19. {

  20. s i%company = Arg

  21. Quit $$$OK

  22. }


  23. }

PHA.YX.Design.Prototype.Resume 增加一个work字段引用WorkExperience

 
   
   
 
  1. Property work As WorkExperience [ Private ];

并且在构造方法初始化它

 
   
   
 
  1. Method %OnNew(name As %String) As %Status [ Private, ServerOnly = 1 ]

  2. {

  3. s $this.name = name

  4. s ..work = ##class(WorkExperience).%New()

  5. Quit $$$OK

  6. }

给对象添加WorkExperience数据方法

 
   
   
 
  1. Method CloneWorkExperience()

  2. {

  3. s ..work = ..work.%ConstructClone()

  4. }

输出也修改一下

 
   
   
 
  1. Method Display()

  2. {

  3. w ..name _ " " _ ..sex _ " " _ ..age,!

  4. w "工作经历:" _ ..timeArea _ " " _ ..company,!

  5. w "工作经历Object:" _ ..work.workDateGet() _ " " _ ..work.companyGet(),!

  6. }

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExampleShallow()

  2. ClassMethod PrototypeExampleShallow()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")

  7. d mResumeA.SetWorkExperienceObject("2010-2011","腾讯")


  8. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  9. s mResumeB = mResumeA.%ConstructClone()

  10. d mResumeB.SetPersonalInfo("男","31")

  11. d mResumeB.SetWorkExperienceObject("2011-2012","阿里")


  12. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  13. s mResumeC =mResumeA.%ConstructClone()

  14. d mResumeC.SetWorkExperience("2017-2020","SS公司")

  15. d mResumeC.SetWorkExperienceObject("2012-2013","百度")


  16. d mResumeA.Display()

  17. d mResumeB.Display()

  18. d mResumeC.Display()

  19. }

 
   
   
 
  1. DHC-APP> d ##class(PHA.YX.Design.Program).PrototypeExampleShallow()

  2. 姚鑫 30

  3. 工作经历:2015-2020 XX公司

  4. 工作经历Object2012-2013 百度

  5. 姚鑫 31

  6. 工作经历:2015-2020 XX公司

  7. 工作经历Object2012-2013 百度

  8. 姚鑫 30

  9. 工作经历:2017-2020 SS公司

  10. 工作经历Object2012-2013 百度

结果发现。引用的字段并没有重新复制。

深复制

我们在PHA.YX.Design.Prototype.Resume里给work属性,增加一个克隆方法。

 
   
   
 
  1. Method CloneWorkExperience()

  2. {

  3. s ..work = ..work.%ConstructClone()

  4. }

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExampleDeep()

  2. ClassMethod PrototypeExampleDeep()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")

  7. d mResumeA.CloneWorkExperience()

  8. d mResumeA.SetWorkExperienceObject("2010-2011","腾讯")


  9. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  10. s mResumeB = mResumeA.%ConstructClone()

  11. d mResumeB.SetPersonalInfo("男","31")

  12. d mResumeB.CloneWorkExperience()

  13. d mResumeB.SetWorkExperienceObject("2011-2012","阿里")


  14. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  15. s mResumeC =mResumeA.%ConstructClone()

  16. d mResumeC.SetWorkExperience("2017-2020","SS公司")

  17. d mResumeC.CloneWorkExperience()

  18. d mResumeC.SetWorkExperienceObject("2012-2013","百度")


  19. d mResumeA.Display()

  20. d mResumeB.Display()

  21. d mResumeC.Display()

  22. }

结果发现,把引用字段work的值也修改成功。

 
   
   
 
  1. DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExampleDeep()

  2. 姚鑫 30

  3. 工作经历:2015-2020 XX公司

  4. 工作经历Object2010-2011 腾讯

  5. 姚鑫 31

  6. 工作经历:2015-2020 XX公司

  7. 工作经历Object2011-2012 阿里

  8. 姚鑫 30

  9. 工作经历:2017-2020 SS公司

  10. 工作经历Object2012-2013 百度

完整示例

简历类(复制类)

 
   
   
 
  1. Class PHA.YX.Design.Prototype.Resume Extends %RegisteredObject

  2. {


  3. Property name As %String [ Private ];


  4. Property sex As %String [ Private ];


  5. Property age As %String [ Private ];


  6. Property timeArea As %String [ Private ];


  7. Property company As %String [ Private ];


  8. Property work As WorkExperience [ Private ];


  9. Method %OnNew(name As %String) As %Status [ Private, ServerOnly = 1 ]

  10. {

  11. s $this.name = name

  12. s ..work = ##class(WorkExperience).%New()

  13. Quit $$$OK

  14. }


  15. Method CloneWorkExperience()

  16. {

  17. s ..work = ..work.%ConstructClone()

  18. }


  19. Method SetPersonalInfo(sex As %String, age As %String)

  20. {

  21. s $this.sex=sex

  22. s $this.age=age

  23. }


  24. Method SetWorkExperience(timeArea As %String, company As %String)

  25. {

  26. s $this.timeArea=timeArea

  27. s $this.company=company

  28. }


  29. Method SetWorkExperienceObject(workDate As %String, company As %String)

  30. {

  31. d ..work.workDateSet(workDate)

  32. d ..work.companySet(company)

  33. }


  34. Method Display()

  35. {

  36. w ..name _ " " _ ..sex _ " " _ ..age,!

  37. w "工作经历:" _ ..timeArea _ " " _ ..company,!

  38. w "工作经历Object:" _ ..work.workDateGet() _ " " _ ..work.companyGet(),!

  39. }


  40. }

对象类(工作经验类)

 
   
   
 
  1. Class PHA.YX.Design.Prototype.WorkExperience Extends %RegisteredObject

  2. {


  3. Property workDate As %String [ Private ];


  4. Method workDateGet() As %String [ ServerOnly = 1 ]

  5. {

  6. Quit i%workDate

  7. }


  8. Method workDateSet(Arg As %String) As %Status [ ServerOnly = 1 ]

  9. {

  10. s i%workDate = Arg

  11. Quit $$$OK

  12. }


  13. Property company As %String [ Private ];


  14. Method companyGet() As %String [ ServerOnly = 1 ]

  15. {

  16. Quit i%company

  17. }


  18. Method companySet(Arg As %String) As %Status [ ServerOnly = 1 ]

  19. {

  20. s i%company = Arg

  21. Quit $$$OK

  22. }


  23. }

调用

 
   
   
 
  1. /// d ##class(PHA.YX.Design.Program).PrototypeExamplePrimary()

  2. ClassMethod PrototypeExamplePrimary()

  3. {

  4. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  5. d mResumeA.SetPersonalInfo("男","30")

  6. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  7. s mResumeB = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  8. d mResumeB.SetPersonalInfo("男","30")

  9. d mResumeB.SetWorkExperience("2015-2020","XX公司")


  10. s mResumeC = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  11. d mResumeC.SetPersonalInfo("男","30")

  12. d mResumeC.SetWorkExperience("2015-2020","XX公司")


  13. d mResumeA.Display()

  14. d mResumeB.Display()

  15. d mResumeC.Display()

  16. }


  17. /// d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()

  18. ClassMethod PrototypeExampleIntermediate()

  19. {

  20. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  21. d mResumeA.SetPersonalInfo("男","30")

  22. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  23. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  24. s mResumeB = mResumeA

  25. d mResumeB.SetPersonalInfo("男","31")


  26. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  27. s mResumeC = mResumeA

  28. d mResumeC.SetWorkExperience("2017-2020","SS公司")

  29. d mResumeA.Display()

  30. d mResumeB.Display()

  31. d mResumeC.Display()

  32. }


  33. /// d ##class(PHA.YX.Design.Program).PrototypeExampleSenior()

  34. ClassMethod PrototypeExampleSenior()

  35. {

  36. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  37. d mResumeA.SetPersonalInfo("男","30")

  38. d mResumeA.SetWorkExperience("2015-2020","XX公司")


  39. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  40. s mResumeB = mResumeA.%ConstructClone()

  41. d mResumeB.SetPersonalInfo("男","31")


  42. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  43. s mResumeC =mResumeA.%ConstructClone()

  44. d mResumeC.SetWorkExperience("2017-2020","SS公司")


  45. d mResumeA.Display()

  46. d mResumeB.Display()

  47. d mResumeC.Display()

  48. }


  49. /// d ##class(PHA.YX.Design.Program).PrototypeExampleShallow()

  50. ClassMethod PrototypeExampleShallow()

  51. {

  52. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  53. d mResumeA.SetPersonalInfo("男","30")

  54. d mResumeA.SetWorkExperience("2015-2020","XX公司")

  55. d mResumeA.SetWorkExperienceObject("2010-2011","腾讯")


  56. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  57. s mResumeB = mResumeA.%ConstructClone()

  58. d mResumeB.SetPersonalInfo("男","31")

  59. d mResumeB.SetWorkExperienceObject("2011-2012","阿里")


  60. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  61. s mResumeC =mResumeA.%ConstructClone()

  62. d mResumeC.SetWorkExperience("2017-2020","SS公司")

  63. d mResumeC.SetWorkExperienceObject("2012-2013","百度")


  64. d mResumeA.Display()

  65. d mResumeB.Display()

  66. d mResumeC.Display()

  67. }


  68. /// d ##class(PHA.YX.Design.Program).PrototypeExampleDeep()

  69. ClassMethod PrototypeExampleDeep()

  70. {

  71. s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")

  72. d mResumeA.SetPersonalInfo("男","30")

  73. d mResumeA.SetWorkExperience("2015-2020","XX公司")

  74. d mResumeA.CloneWorkExperience()

  75. d mResumeA.SetWorkExperienceObject("2010-2011","腾讯")


  76. # dim mResumeB as PHA.YX.Design.Prototype.Resume

  77. s mResumeB = mResumeA.%ConstructClone()

  78. d mResumeB.SetPersonalInfo("男","31")

  79. d mResumeB.CloneWorkExperience()

  80. d mResumeB.SetWorkExperienceObject("2011-2012","阿里")


  81. # dim mResumeC as PHA.YX.Design.Prototype.Resume

  82. s mResumeC =mResumeA.%ConstructClone()

  83. d mResumeC.SetWorkExperience("2017-2020","SS公司")

  84. d mResumeC.CloneWorkExperience()

  85. d mResumeC.SetWorkExperienceObject("2012-2013","百度")


  86. d mResumeA.Display()

  87. d mResumeB.Display()

  88. d mResumeC.Display()

  89. }

思考

用深复制实现,Java,Python,C#,连接Caché数据库(有连接属性,连接时间),Caché数据库持有SQL数据库连接(有连接属性,连接时间)。感兴趣的同学实现后可以发我一起参考下。


以上是关于第六章 Caché 设计模式 原型模式的主要内容,如果未能解决你的问题,请参考以下文章

第十六章 Caché 算法与数据结构 计数排序

Caché高级开发—设计模式 培训总结

第八章 Caché 设计模式 外观模式

第四章 Caché 设计模式 代理模式

第六章:继承

第十七章 Caché 设计模式 单例模式