构建通用类型- 继承 VS 聚合
?
繼承和聚合的比較GoF[1]做了詳盡的闡述,在此偶將從實(shí)踐的角度用一個(gè)例子來提供一種比較通用的解決方案,對(duì)繼承和聚合做一個(gè)適用本案例的選擇。此文乃一個(gè)案,并不代表兩者的絕對(duì)優(yōu)劣,具體問題還是要具體分析。
?
【問題】
在CAD或畫圖軟件設(shè)計(jì)設(shè)計(jì)中,會(huì)存在大量的基本體[2],如line、 circle、arc、 polyline、 sphere、 box等。在組織它們之間的關(guān)系的時(shí)候,一般會(huì)有如下的繼承體系:
圖表 1 基本體類結(jié)構(gòu)
?
即對(duì)每一種基本體,都有一個(gè)class與之對(duì)應(yīng)。若有100種基本體,那就得有100個(gè)class從Entity繼承而來。
但從這些class本身來看,問題并沒有多么嚴(yán)重,畢竟不同的基本體總得有個(gè)class或object異或別的什么東西與之對(duì)應(yīng)。一個(gè)完整的畫圖軟件總得有序列化機(jī)制、總得有個(gè)undo/redo機(jī)制、總得有個(gè)界面顯示這些紛紛亂亂的基本體的參數(shù)以供交互式操作吧。因此,每個(gè)類又得加入save/load操作,undo/redo支持,再加上套UI class[3]。記得N年前做的一個(gè)CAX項(xiàng)目中,但為基本體寫UI class就花了2W行代碼,現(xiàn)在想想有些汗顏。
?
圖表 2 屬性類與基本體類關(guān)系
圖表 3?CAD示例
?
在寫了N多相似的類后未免讓人厭倦,讓人有種重構(gòu)的沖動(dòng)。實(shí)現(xiàn)界面與數(shù)據(jù)分離可以使用腳本的辦法,在此不作贅述。
?
【解決方案】
對(duì)于一個(gè)繪圖程序,其基本體主要有兩部分內(nèi)容:參數(shù) + 構(gòu)建方法。各種基本體之間的差異也存在于此。數(shù)據(jù)部分可以用一個(gè)variant[4]容器統(tǒng)一來描述,通過一個(gè)參數(shù)ID提取不同的參數(shù)。差異最大在于創(chuàng)建實(shí)體的方法,即作用于參數(shù)的行為。再次抽象后,通用基本體類型層次關(guān)系如下:
圖表 4 通用基本體類型類結(jié)構(gòu)
?
各種基本體類型都用Primitive統(tǒng)一描述,不再?gòu)乃^承子類,而是實(shí)現(xiàn)不同的創(chuàng)建基本體的BuildMethod。最后用一個(gè)Factory模式管理各種BuildMethod,根據(jù)與Primitive綁定的BuildMethod ID,創(chuàng)建幾何形狀。
?
由此所帶來的好處是:
1.?????? Save/Load只需要在Primitive實(shí)現(xiàn)
2.?????? Undo/Redo只需要在Primitive實(shí)現(xiàn)
3.?????? 可以從Primitive的參數(shù)類型描述中提出GUI表現(xiàn)形式[5]
4.?????? 可擴(kuò)展性得到增強(qiáng),新增的類型無需考慮以上三條。
?
由此所帶來最大的壞處就是性能上有所損失。從variant得到具體的數(shù)據(jù)類型畢竟沒有直接用原始的數(shù)據(jù)類型來的高效些。從使用的效果來看,并不會(huì)產(chǎn)生用戶交互上的延遲。
?
【總結(jié)】
???????? 前后兩種方法的主要差別在于是使用繼承還是聚合,以及是如何使用繼承的。二者本身沒有優(yōu)劣之分,但在具體的情景下就需要權(quán)衡利弊。
????????
--- 力為
?
[1] 《設(shè)計(jì)模式》
[2] 指基本幾何類型。不知道這世界上有多少基本體,在不同的領(lǐng)域中可能基本體的定義也不盡相同。建筑中,可能門,窗都算作是基本體。
[3] boost::serialization?提供了一種非侵入式的序列化方法,值得一試。
Undo/redo的實(shí)現(xiàn)可以參考GoF的Memento Pattern.
[4] variant的實(shí)現(xiàn)有多種方法,boost有兩種,參考boost::any 與 boost::variant 的區(qū)別。
[5] 提取形式亦可參考如何從腳本提取UI的實(shí)現(xiàn)方法。
?轉(zhuǎn)載于:https://www.cnblogs.com/wuwuwu/archive/2008/04/04/6335199.html
總結(jié)
以上是生活随笔為你收集整理的构建通用类型- 继承 VS 聚合的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [导入]C++ GUi 选择
- 下一篇: PDF阅读器Foxit Reader 2