首先, 我覺得如果你對物件導向設計的資訊系統感興趣, 可以看看martin fowler的《企業應用架構模式》。簡單的說兩句, 對於乙個繼承體系, 至少有三種建立關係模型的方式:
1. 乙個老師表, 但是這個老師表, 同時有欄位對應教授和講師的屬性, 乙個教授的行, 其講師的字段是空的, 乙個講師的行, 其教師特有的字段是空的。 對於很多現代資料庫來說, 其冗餘的cell是不會占用儲存空間的。
2. 假設沒有老師這一具體職位(也就是說老師是抽象的基類),乙個講師表, 乙個教授表, 這兩個表具有一些相同的字段, 既教授和講師共同具有的屬於老師的特性的字段。
3. 有老師表, 講師表, 和教授表三個表。 講師表僅儲存講師的特性, 教授表僅儲存教授的特性。 繼承體系可能是這兩種(講師 教授),或(老師->講師->教授), 但無論是哪種, 子類通過父類的id, 和父類表向鏈結。 比如, 無論多了乙個教授, 還是乙個講師, 老師表裡都會增加一條老師記錄, 如果是講師, 同時在講師表裡插入講師特有的資訊, 如果是教授, 則同時在教授表裡插入教授特有的資訊。
所以, 對於乙個繼承體系來講, 不見得在現實裡只有乙個表。 另外一點, 我個人認為, 這些不同的表的劃分方式, 其實即使沒有物件導向設計, 也是合理的, 同時自有其判斷依據: 比如方式3, 有些場景, 我們僅僅需要老師的那些特性, 所以僅訪問老師表即可; 有時候我們可能僅處理教授的特性, 而那些作為老師的共同特性反而不關心。 一旦我們關心全部特性, 我們可以將表連線起來。
以上三種方式, 都有乙個前提, 既講師和教授, 都有比起其父類, 更多的特性。 如果講師和教授, 僅僅是身份不同, 像你說的, 最多有乙個標誌為標識其身份,我們不談物件導向, 就談對這件事的認識。
在現實生活中, 講師和教授也許是有很多不同點, 以至於我們必須明確的分割這兩種身份。 但是我們就我們所處理的任務的角度, 他們或許沒什麼不同: 系統內部只關心他們作為老師的一些特性; 而一些差異, 則僅僅是是乙個子特性, 沒有必要甚至不能夠,上公升到讓這兩種身份在*任務的視角上*產生真正的差異。
比如: 我們給不同身份的人發不同的工資。 這些僅僅是我們根據特性展開的, 其具體內容屬於另一範疇的東西, 對於老師這乙個概念來說, 身份只是乙個很普通的標誌, 就好比他是男還是女一樣。 因為大多數關心的主要任務和這個屬性關係不大, 所以就不會在系統內部設立兩個不同的概念。 比如男的上男廁所, 女的上女廁所, 這是乙個額外的規矩, 是在與人這個概念關係不大的其它部分進行的; 但是如果我們任務關心的問題, 就是女人和男人的差別, 情況則不同了。 比如女人和男人的體貌、 行為、 性格, 這些特點如果是我們要處理的, 很顯然, 我們應該明確劃分這兩個概念。 從物件導向、特別是繼承的觀點來看, 我們需要至少兩個物件; 當我們有時候同時關心男女共同為人的特點時, 我們還需要乙個叫做「人」的基類物件。
在建表時, 也就會產生我上面所說的三種方式的不同差異。 至於三種方式的優劣, 暫時不能逐一展開, 不過fowler那本書裡都有提到; 不過讀哪本書時, 可千萬別當成什麼金科玉律, 肺炎的種類很多, 不是吃茴香都能治的。
不過我們至少可以看出, 我們如何建表, 如何找到合適的模型, 並非是照搬現實生活裡存在的概念的; 而是從我們的任務的視角上看過去, 存在哪些概念。 後者的判斷, 在於我們關心些什麼, 關心的這些內容, 造成了哪些程度上的不同, 有很大不同的時候, 我們需要不同的表達, 沒有不同時, 我們就採用統一的表達。 而類設計和表設計, 只是我們表達的體現而已。 那麼, 你所面對的問題, 從各方面來看, 需要幾種表達方式才能完善呢?
同時, 我們在這時候, 不要過多的去考慮全域性到具體, 而是把問題割裂開。 這個事情和談戀愛正好相反,粘在一起的東西, 扯開比較費勁; 而把東西粘起來, 則相對容易。 這是因為我們人腦同一時間可以理清的東西有限。 所以我們要明確的認識到, 哪些東西可以規劃到「男人上男廁所, 女人上女廁所」這樣的外部規則, 哪些東西滿足「男人和女人不同的特徵」。 如果一時不容易分清, 至少我們在資訊的量上可以做把握(不過這樣把握的方式其實不是實質性的, 隨著理解的深入, 就要放棄了), 後者往往涉及到一系列資訊, 而前者中「男」「女」僅僅是乙個用於填入規則的標誌。
當然, 我們設計了乙個表, 其中有乙個字段儲存「男」、「女」, 進行物件導向的設計的時候, 我們照樣可以弄出一大堆類, 繼承人這個類。 當我們呼叫, 人.上廁所()時, 就各去各的廁所了。 物件導向一般鼓勵以這樣的方式, 去給出統一的介面(比如這個例子裡「人」)。 其優勢在於, 當我們多出其它性別時, 比如「半男半女」、「不男不女」, 那些呼叫「人.上廁所()」的**, 全都無需改變。
這裡有乙個假設, 在於「人」這個介面, 比如具有一些屬性, 具有乙個「上廁所」的方法, 這個介面是穩定的, 不會改變的。 當我們在進行設計時, 要衡量這個假設是不是成立的。 比如上廁所這個行為, 有可能在未來變化為「上廁所(帶手紙)」, 「上廁所(沒帶紙)」, 這樣乙個介面的變動。 很多物件導向設計只所以問題連連, 就在於做出了時效性太強的假設。
為什麼這麼說呢?因為介面是有很大概率會變化的, 其區別僅僅是乙個月之內就變, 還是這個系統用了3年才變。介面一旦發生變動, 我們往往就要為當初獲得的好處埋單了。所以如何設計, 有時候不是乙個絕對化的問題, 而是乙個想辦法付出最小代價的問題。
對於上廁所, 我們可以統一的把上廁所的具體問題外包出去, 比如針對各種情況可能採取的各種方式, 這樣我們就產生乙個「上廁所的辦法」這樣乙個外部概念。 我們可以想像, 當乙個人腦子裡有這個概念的時候(「人」這個類別的物件持有某一「上廁所策略」), 就可以根據判斷「我是女的, 我上女廁」、「我沒帶紙、找張報紙」進行行為, 你可以說這些是這女的想的, 但是你也可以認為這些僅僅是外部規則, 這女的只是按照規則機械的行動而已; 這後一種看法, 實際上使得我們容易在計算機上設計。
這時候, 我們無需使用繼承的體系, 而是採用「人.上廁所(策略)」這樣的介面, 那麼如果我們所關心的「男」、「女」, 和帶紙沒帶紙一樣, 僅僅是上廁所策略用以判斷的素材而已; 這樣, 我們就不需要男人類和女人類了。
從以上例子來看, 類的設計和表的設計, 不是說一定要有必然的聯絡。 因為既然我們寫了非訪問的**, 就說明我們除了可以記錄下來的特徵, 還關心其它的非可固化性質的行為, 那麼我們如何設計類、 物件, 則必須從這些行為以及系統中各個物件互動的視角上出發, 而不是考慮我們的表如何設計的。 注意, 這不是說我贊成以實體類去設計表, 關係模型關心和表現的是事情的另乙個側面, 所以設計表恰恰不能從物件設計倒回去。 它們之間應該是正交的, 不要存在乙個依賴另外乙個這樣的耦合。 如何讓他們相容, 需要且應該做額外的工作。
當上面的例子簡化到一定地步, 比如 if(男) ... else ...時, 我們也不需要什麼策略的物件或者類, 有一些用於體現策略指令碼處理即可。 到了這個地步, 我們也許乙個實體類都不需要有。 我們就簡單的把系統看作根據具體情況作出判斷和處理的策略系統就可以了, 這時候我們需要的僅僅是資訊的載體, 這就是為什麼我經常會說, 當產生了貧血物件後, 我們要考慮的不是把它變複雜, 而是看看能不能把它從系統中抹去的原因。 很多時候, 貧血模擬起乙個通用的資訊載體, 除了欄位和屬性強型別的好處, 僅僅發揮乙個自身標識的作用; 但是當我們呼叫「人能做的事情靜態幫助類.上廁所(資訊載體)」的時候, 實際上我們已經隱式的傳遞了這個標識; 我們也可以設定一些具體的手法, 保證安全。
最後, 我們再來看看這些區別, 強化一下印象:
1. 「人能做的事情.上廁所(資訊載體)」、「人.上廁所()」和「人.上廁所(策略)」之間如何取捨, 在於複雜度, 複雜度上公升到一定程度, 我們要採取後者; 這是為了避免前者「上廁所」這一rotine其內部複雜度上公升的太高, 或者被頻繁修改。 另外乙個更明確的判斷點在於, 人是否帶有可變化的狀態; 上廁所這件事是否有很多的方式。
2. 假設我們採取了含有「人」這一樣乙個概念的具體表達的設計, 人這個介面如何保持穩定是我們要注意的。 比如「上廁所」這一行為隱含的變化, 或者又增加「吃飯」等行為, 都屬於介面的不穩定, 如果這種不穩定在短期內就會出現, 我們應該把行為和規則外包給其它概念, 而不是讓它們依附在人之上。 如果我們一出生就是狼孩, 本來我們也不會具有這些概念所指的行為; 並不是說「主語.謂語」, 這樣的設計方式就是合理的。
3. 我們是否需要「男人」、「女人」 或者 「講師」、 「教授」 這樣的繼承體系, 可以這樣判斷: 必須共性大、同時差異也大。 組合比繼承好, 這是從95年《設計模式》以後被大家廣泛接受的原則。 很顯然, 共性和差異同時非常大的情況不是特別多見。 也許我們平時見慣了我們的aspx頁面繼承於page, page又繼承於templatecontrol和control。 且不說合理與否, 這並不能說明需要繼承的情況很多。 因為這樣乙個繼承, 使用了10000遍, 它其實還是乙個繼承。
4. 表設計和物件設計是兩碼事, 要按照各自的特點來做; 同時追求兩邊的合理性, 要付出的代價就是多做中間工作, 這些上面說的比較詳細, 就不多說了。唯一可以說的是, 在成本上考慮, 我們要做好折中的選擇。 更多的則是, 無論哪個設計, 無論什麼設計方法, 我們別想太多, 更多的要找出我們關心的全部內容, 而不要把在現實生活中的知識帶入過多; 因為對我們要解決的問題所在視角, 這些知識可能就成了不必要的偏見, 或者至少像用大學物理解釋初中物理題。
這些問題其實在學習物件導向以後, 做類似的資訊管理時, 非常普遍。 我想你先問問自己, 你自己想採用什麼樣的設計呢? 其次, 看看自己能不能找到這種設計的擴充套件或靈活性的好處。很多時候, 我感覺咱們想物件導向的衝動, 是因為不物件導向, 好像就不是乙個設計, 簡陋了些。 首先要克服這個心理。 如果找不到乙個設計的好處, 而非要物件導向的話,即使存在一些好處, 也不是我們可以掌握的; 如果反而添了不少麻煩, 這些麻煩也不容易被找到。
總而言之, 我覺得, 不求巧, 但求拙, 不給自己的思路下套子, 不引入過多的雜念, 是設計的一些好的準則。
關於翻譯隨便說兩句
去年11月份翻譯的 ios遊戲開發入門經典 一書已經上市發行了,剛剛拿到清華出版社寄來的樣書,心裡不免有些小激動。近期,我的第二本書又在緊鑼密鼓的翻譯之中了,這也是一本ios遊戲開發方面的入門書籍。不過與第一本書不同之處在於,這本書中涉及到很多重構和抽象的內容。而且通過不斷地封裝重構,最終構建出乙個...
嘮叨兩句 Event and delegate
delegate 當委託被呼叫時,委託例項 delegate 委託 某人 method 去做某事 action 即可表示為 delegate method event 當事件發生時,事件 event 通知 委託例項 delegate 事件 event 發生了 然後 委託例項 delegate 委託 ...
有關教育兩句名言
學生的頭腦不是乙個等待填滿的容器,而是一支需要被點燃的火把。楊福家教授 楊福家,著名核物理學家。1936年6月生,1958年畢業於復旦大學物理系。1991年當選為中國科學院院士,1993年2月任復旦大學校長。2001年1月,英國諾丁漢大學校董會宣布,鑑於 楊福家教授的科學成就及國際影響 正式聘請楊為...