第六章 Caché 設(shè)計模式 原型模式
定義
- 用原型實例指定創(chuàng)建對象的種類订歪,并且通過拷貝這些原型創(chuàng)建新的對象串结。
- 原型模式其實就是從一個對象再創(chuàng)建另外一個可定制的對象,而且不需要知道任何創(chuàng)建的細(xì)節(jié)自点。
使用場景
使用原形模式可以解決復(fù)雜對象構(gòu)建資源消耗的問題生音。也可以用來只讀保護(hù)。注意其java里繼承Cloneable接口缩麸。C#繼承ICloneable接口铸磅。Caché 直接使用%ConstructClone()方法,克隆時不會走構(gòu)造函數(shù)杭朱。
優(yōu)點
- 一般在初始化的信息不發(fā)生變的情況下阅仔,克隆是最好的辦法,這即隱藏了對象創(chuàng)建的細(xì)節(jié)弧械,又對性能是大大的提高八酒。
- 不用重新初始化對象,而是動態(tài)地獲得對象運行時的狀態(tài)刃唐。
結(jié)構(gòu)圖
描述
要求有一個簡歷類羞迷,必須要有姓名,可以設(shè)置性別和年齡画饥,可以設(shè)置工作經(jīng)歷衔瓮。最終需要三分簡歷。
示例
簡歷類
Class PHA.YX.Design.Prototype.Resume Extends %RegisteredObject
{
Property name As %String [ Private ];
Property sex As %String [ Private ];
Property age As %String [ Private ];
Property timeArea As %String [ Private ];
Property company As %String [ Private ];
Method %OnNew(name As %String) As %Status [ Private, ServerOnly = 1 ]
{
s $this.name = name
Quit $$$OK
}
Method SetPersonalInfo(sex As %String, age As %String)
{
s $this.sex=sex
s $this.age=age
}
Method SetWorkExperience(timeArea As %String, company As %String)
{
s $this.timeArea=timeArea
s $this.company=company
}
Method Display()
{
w ..name _ " " _ ..sex _ " " _ ..age,!
w "工作經(jīng)歷:" _ ..timeArea _ " " _ ..company,!
}
}
初級寫法
/// d ##class(PHA.YX.Design.Program).PrototypeExamplePrimary()
ClassMethod PrototypeExamplePrimary()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
s mResumeB = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeB.SetPersonalInfo("男","30")
d mResumeB.SetWorkExperience("2015-2020","XX公司")
s mResumeC = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeC.SetPersonalInfo("男","30")
d mResumeC.SetWorkExperience("2015-2020","XX公司")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExamplePrimary()
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
缺點
三分簡歷需要實例化三次抖甘,如果需要一百份热鞍,就需要實例化一百次,徒增內(nèi)存。
中級寫法
/// d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()
ClassMethod PrototypeExampleIntermediate()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC = mResumeA
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
缺點
引用傳值薇宠,改動其中一處其他復(fù)制實例一起改動偷办。把mResumeB設(shè)置一下年齡,mResumeC設(shè)置一下公司昼接。如下:
/// d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()
ClassMethod PrototypeExampleIntermediate()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA
d mResumeB.SetPersonalInfo("男","31")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC = mResumeA
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
運行結(jié)果
DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()
姚鑫 男 31
工作經(jīng)歷:2017-2020 SS公司
姚鑫 男 31
工作經(jīng)歷:2017-2020 SS公司
姚鑫 男 31
工作經(jīng)歷:2017-2020 SS公司
高級寫法 (淺復(fù)制)
使用 .%ConstructClone()方法復(fù)制
/// d ##class(PHA.YX.Design.Program).PrototypeExampleSenior()
ClassMethod PrototypeExampleSenior()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA.%ConstructClone()
d mResumeB.SetPersonalInfo("男","31")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC =mResumeA.%ConstructClone()
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
DHC-APP> d ##class(PHA.YX.Design.Program).PrototypeExampleSenior()
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
姚鑫 男 31
工作經(jīng)歷:2015-2020 XX公司
姚鑫 男 30
工作經(jīng)歷:2017-2020 SS公司
淺復(fù)制
如果字段是值類型的爽篷,則對該字段執(zhí)行逐位復(fù)制,如果字段是引用類型慢睡,則復(fù)制引用但不復(fù)制引用的對象逐工,因此原始對象及其副本引用統(tǒng)一對象。如下增加一個工作經(jīng)驗類的引用字段:
增加一個WorkExperience類
Class PHA.YX.Design.Prototype.WorkExperience Extends %RegisteredObject
{
Property workDate As %String [ Private ];
Method workDateGet() As %String [ ServerOnly = 1 ]
{
Quit i%workDate
}
Method workDateSet(Arg As %String) As %Status [ ServerOnly = 1 ]
{
s i%workDate = Arg
Quit $$$OK
}
Property company As %String [ Private ];
Method companyGet() As %String [ ServerOnly = 1 ]
{
Quit i%company
}
Method companySet(Arg As %String) As %Status [ ServerOnly = 1 ]
{
s i%company = Arg
Quit $$$OK
}
}
PHA.YX.Design.Prototype.Resume 增加一個work字段引用WorkExperience
Property work As WorkExperience [ Private ];
并且在構(gòu)造方法初始化它
Method %OnNew(name As %String) As %Status [ Private, ServerOnly = 1 ]
{
s $this.name = name
s ..work = ##class(WorkExperience).%New()
Quit $$$OK
}
給對象添加WorkExperience數(shù)據(jù)方法
Method CloneWorkExperience()
{
s ..work = ..work.%ConstructClone()
}
輸出也修改一下
Method Display()
{
w ..name _ " " _ ..sex _ " " _ ..age,!
w "工作經(jīng)歷:" _ ..timeArea _ " " _ ..company,!
w "工作經(jīng)歷Object:" _ ..work.workDateGet() _ " " _ ..work.companyGet(),!
}
/// d ##class(PHA.YX.Design.Program).PrototypeExampleShallow()
ClassMethod PrototypeExampleShallow()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
d mResumeA.SetWorkExperienceObject("2010-2011","騰訊")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA.%ConstructClone()
d mResumeB.SetPersonalInfo("男","31")
d mResumeB.SetWorkExperienceObject("2011-2012","阿里")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC =mResumeA.%ConstructClone()
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeC.SetWorkExperienceObject("2012-2013","百度")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
DHC-APP> d ##class(PHA.YX.Design.Program).PrototypeExampleShallow()
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
工作經(jīng)歷Object:2012-2013 百度
姚鑫 男 31
工作經(jīng)歷:2015-2020 XX公司
工作經(jīng)歷Object:2012-2013 百度
姚鑫 男 30
工作經(jīng)歷:2017-2020 SS公司
工作經(jīng)歷Object:2012-2013 百度
結(jié)果發(fā)現(xiàn)漂辐。引用的字段并沒有重新復(fù)制泪喊。
深復(fù)制
我們在PHA.YX.Design.Prototype.Resume里給work屬性,增加一個克隆方法髓涯。
Method CloneWorkExperience()
{
s ..work = ..work.%ConstructClone()
}
/// d ##class(PHA.YX.Design.Program).PrototypeExampleDeep()
ClassMethod PrototypeExampleDeep()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
d mResumeA.CloneWorkExperience()
d mResumeA.SetWorkExperienceObject("2010-2011","騰訊")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA.%ConstructClone()
d mResumeB.SetPersonalInfo("男","31")
d mResumeB.CloneWorkExperience()
d mResumeB.SetWorkExperienceObject("2011-2012","阿里")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC =mResumeA.%ConstructClone()
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeC.CloneWorkExperience()
d mResumeC.SetWorkExperienceObject("2012-2013","百度")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
結(jié)果發(fā)現(xiàn)袒啼,把引用字段work的值也修改成功。
DHC-APP>d ##class(PHA.YX.Design.Program).PrototypeExampleDeep()
姚鑫 男 30
工作經(jīng)歷:2015-2020 XX公司
工作經(jīng)歷Object:2010-2011 騰訊
姚鑫 男 31
工作經(jīng)歷:2015-2020 XX公司
工作經(jīng)歷Object:2011-2012 阿里
姚鑫 男 30
工作經(jīng)歷:2017-2020 SS公司
工作經(jīng)歷Object:2012-2013 百度
完整示例
簡歷類(復(fù)制類)
Class PHA.YX.Design.Prototype.Resume Extends %RegisteredObject
{
Property name As %String [ Private ];
Property sex As %String [ Private ];
Property age As %String [ Private ];
Property timeArea As %String [ Private ];
Property company As %String [ Private ];
Property work As WorkExperience [ Private ];
Method %OnNew(name As %String) As %Status [ Private, ServerOnly = 1 ]
{
s $this.name = name
s ..work = ##class(WorkExperience).%New()
Quit $$$OK
}
Method CloneWorkExperience()
{
s ..work = ..work.%ConstructClone()
}
Method SetPersonalInfo(sex As %String, age As %String)
{
s $this.sex=sex
s $this.age=age
}
Method SetWorkExperience(timeArea As %String, company As %String)
{
s $this.timeArea=timeArea
s $this.company=company
}
Method SetWorkExperienceObject(workDate As %String, company As %String)
{
d ..work.workDateSet(workDate)
d ..work.companySet(company)
}
Method Display()
{
w ..name _ " " _ ..sex _ " " _ ..age,!
w "工作經(jīng)歷:" _ ..timeArea _ " " _ ..company,!
w "工作經(jīng)歷Object:" _ ..work.workDateGet() _ " " _ ..work.companyGet(),!
}
}
對象類(工作經(jīng)驗類)
Class PHA.YX.Design.Prototype.WorkExperience Extends %RegisteredObject
{
Property workDate As %String [ Private ];
Method workDateGet() As %String [ ServerOnly = 1 ]
{
Quit i%workDate
}
Method workDateSet(Arg As %String) As %Status [ ServerOnly = 1 ]
{
s i%workDate = Arg
Quit $$$OK
}
Property company As %String [ Private ];
Method companyGet() As %String [ ServerOnly = 1 ]
{
Quit i%company
}
Method companySet(Arg As %String) As %Status [ ServerOnly = 1 ]
{
s i%company = Arg
Quit $$$OK
}
}
調(diào)用
/// d ##class(PHA.YX.Design.Program).PrototypeExamplePrimary()
ClassMethod PrototypeExamplePrimary()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
s mResumeB = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeB.SetPersonalInfo("男","30")
d mResumeB.SetWorkExperience("2015-2020","XX公司")
s mResumeC = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeC.SetPersonalInfo("男","30")
d mResumeC.SetWorkExperience("2015-2020","XX公司")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
/// d ##class(PHA.YX.Design.Program).PrototypeExampleIntermediate()
ClassMethod PrototypeExampleIntermediate()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA
d mResumeB.SetPersonalInfo("男","31")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC = mResumeA
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
/// d ##class(PHA.YX.Design.Program).PrototypeExampleSenior()
ClassMethod PrototypeExampleSenior()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA.%ConstructClone()
d mResumeB.SetPersonalInfo("男","31")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC =mResumeA.%ConstructClone()
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
/// d ##class(PHA.YX.Design.Program).PrototypeExampleShallow()
ClassMethod PrototypeExampleShallow()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
d mResumeA.SetWorkExperienceObject("2010-2011","騰訊")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA.%ConstructClone()
d mResumeB.SetPersonalInfo("男","31")
d mResumeB.SetWorkExperienceObject("2011-2012","阿里")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC =mResumeA.%ConstructClone()
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeC.SetWorkExperienceObject("2012-2013","百度")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
/// d ##class(PHA.YX.Design.Program).PrototypeExampleDeep()
ClassMethod PrototypeExampleDeep()
{
s mResumeA = ##class(PHA.YX.Design.Prototype.Resume).%New("姚鑫")
d mResumeA.SetPersonalInfo("男","30")
d mResumeA.SetWorkExperience("2015-2020","XX公司")
d mResumeA.CloneWorkExperience()
d mResumeA.SetWorkExperienceObject("2010-2011","騰訊")
# dim mResumeB as PHA.YX.Design.Prototype.Resume
s mResumeB = mResumeA.%ConstructClone()
d mResumeB.SetPersonalInfo("男","31")
d mResumeB.CloneWorkExperience()
d mResumeB.SetWorkExperienceObject("2011-2012","阿里")
# dim mResumeC as PHA.YX.Design.Prototype.Resume
s mResumeC =mResumeA.%ConstructClone()
d mResumeC.SetWorkExperience("2017-2020","SS公司")
d mResumeC.CloneWorkExperience()
d mResumeC.SetWorkExperienceObject("2012-2013","百度")
d mResumeA.Display()
d mResumeB.Display()
d mResumeC.Display()
}
思考
用深復(fù)制實現(xiàn)纬纪,Java蚓再,Python,C#包各,連接Caché數(shù)據(jù)庫(有連接屬性摘仅,連接時間),Caché數(shù)據(jù)庫持有SQL數(shù)據(jù)庫連接(有連接屬性问畅,連接時間)娃属。感興趣的同學(xué)實現(xiàn)后可以發(fā)我一起參考下。