熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

試簡單概括面向對象接口編程

2013-11-23 18:52:57  來源: Java核心技術 

  本文不是為了論證面向對象方法論那需要深厚的理論知識和豐富的實踐經驗本人兩方面都差得很遠
  這裡只是試圖給出一個對面象接口的深入淺出的簡單原則
  就象數學很難數論很難但是九九表不難各位數字之和被整除推出這個整數能被整除也不難(但是兩者都很有用)
  
  其實總感覺oo被多數人都誤解了Fp世界的人一說oo必然就拿出oo的類呀繼承啊來和fp比較一番多態被他們理解為在繼承中的一種定制(也就是override了)
  
  而oo世界中的人呢有的也是抱著類繼承不放增量設計是他們的聖經有的則是捧著一本本經典的面向對象著作念經什麼design pattern拉refactoring啦OO software construction啦孜孜不倦地一個一個原則一個一個定義一個一個模式地反復辨析所謂讀書破萬卷下筆如有神啊書上很多微言大義被反復引用到處套用但是有時候卻總是看上去不是那麼回事同一句話可以被兩個人引用卻得到不同的結論就象都是讀新約的Christian卻搞出了天主教新教等等互指為異端的教派到底是書錯了?還是讀書的人錯了?
  
  個人最討厭故弄玄虛把簡單的事情搞復雜這裡讓我試試能不能簡單地解釋一下面向接口這個oo原則
  
  任何軟件都是由各種不同的模塊組成的(沒錯最小的軟件如一個hello world 也是)
  從自頂向下的觀點看一個大模塊由若干個小模塊組成一個小模塊又由若干個更小的模塊組成就象大樓由磚造成磚由分子組成分子由原子組成一樣
  
  這些模塊之間不可能是互相獨立的相互之間肯定要有各種關系
  
  這些關系可以被總結為簡單的兩種
  需求和服務
  需求就是我要求別人給我提供什麼樣功能的服務
  服務就是我提供一個什麼樣功能的服務
  
  所有的關系都是這樣兩個原子關系的組合
  當設計任何一個模塊的時候你所看見的就只應該是這個模塊對外界的需求和要提供的服務你不應該看見隔著十萬八千裡的模塊乙也不應該看到容器或者配置文件是如何把模塊們(包括你現在設計的模塊)組裝起來的那些都屬於另外一個維度另外一個和你不相交的宇宙空間的事
  
  一些c++同志喜歡二分法軟件在他們那裡變成一個簡單的庫用戶這樣的結構在他們看來庫可以任意復雜只要給用戶提供一個簡單的接口就夠了
  他們沒有看到所謂的用戶的劃分是相對的而不是絕對的一個模塊提供一定的功能那麼它相對於使用它的功能的模塊就是一個而這個模塊可能還要別人提供一些功能那麼象對於提供這些服務的模塊它又是用戶
  
  兩個模塊很又可能互相都是用戶也都是庫(只不過相對於不同的服務層面不同的維度而已)
  
  這樣的服務/需求的關系遍布於軟件的各個地方
  而所謂oo 面向接口就是用來管理這些依賴關系的
  就象你整理自己的計算機網絡布線或者電視機後面的各種顏色的線一樣oo也就是一套行之有效的整理這些關系讓它們不要變成一團亂麻的經驗之談
  
  任何一個理論系統要想優美就要遵循下面的准則
  完整
  自恰
  簡單
  
  比如幾何學用了幾條最簡單的互相不相關的(所謂正交是也)的公理組建出了一個宏偉的大廈
  
  面向對象的設計原則也應該如此我試著給出下面兩個公理讓我們看看能不能
  .完整地描述面向對象方法
  .不自相矛盾
  .簡單
  
  原則A需求者只要求自己需要的ask no more ask no less!
  原則B服務者只提供最小的能夠提供足夠功能的界面 promise no more promise no less!
  
  從這兩個原則我們試著推演一下其它的許多oo的准則來
  
  .Ioc原則或者dip原則所謂具體依賴抽象抽象不依賴具體這是關於需求者的一個設計方法
  遇到一個需要的功能這個功能的實現實際上和我自己模塊的實現不相關正交所以我定義一個接口從外界注射進來一個實現
  
  那麼用原則A是怎麼得到這個准則的呢?
  首先ask no less 所以如果功能不是和我正交的那麼僅僅定義一個接口從外界注射進來對我就不夠不符合no less比如我的實現碰巧讓我需要一個InputStreamReader而不能是StringReader那麼如果僅僅從外界注射進來一個Reader對我的實現來說它達不到我的要求
  所以根據no less ioc進來的需要是和當前模塊實現正交的
  
  然後no more如果我不用ioc直接自己new一個FileReader如何?本來只需要InputStreamReader 你卻要求它的子類型FileReader? 明顯違反了no more的要求
  
  再舉個例子ioc要求不要new而是從外界注射那麼是不是說我們就永遠不能new呢?永遠都不能Xinstance()呢?
  當然不是注意我們的前提是正交是no less
  
  假如我有一個抽象工廠
  
  java代碼: 
  
   interface PersistenceFactory{
  }
     Persistence create();
   }
  
  那麼當實現這個工廠的jdbc實現的時候很可能是這樣
  java代碼: 
  
   class JdbcPersistenceFactory{
  }
    Persistence create(){
  }
      Return JdbcPersistenceinstance();
     }
   }
  
  這裡你用了一個靜態工廠直接依賴於JdbcPersistence實現類了是不是違反了ioc規則呢?
  當然不是請注意我們的模塊本身就是實現JdbcPersistence的那麼從外界再ioc一個PersistenceFactory或者Persistence就不符合正交no less的要求了
  
  而且其實從常識就可以看出來你JdbcPersistenceFactory的任務就是生成一個關於jdbc的PersistenceFactory你如果自己不做再ioc進來這層層推诿真正的工作誰做呢?
  
  .Lsp所謂任何地方如果你期待的是一個父類型Base那麼把它替換成任何的子類型Derived Derived程序都能正常工作
  還是關於需求者的如果你做到了ask no more比如說你只需要Base提供的功能就不要在接口上要求Derived Derived如此我們自然可以任意替換實際的實現
  如果你做到了ask no less需要InputStreamReader就直接要求InputStreamReader而不是Reader你就不會需要在代碼中做downcast到InputStreamReader的動作也就不會出現把Reader替換成StringReader之後出現的運行時錯誤
  
  .單一職責原則一個模塊只應該做一件事
  仍然是需求者的設計方法這裡的的概念應該是一個正交於其它的功能兩個互相緊密耦合的其實是一件事
  根據ask no more如果一個模塊做了兩件正交的事也就是把兩個正交的模塊耦合在一起就意味著在我這個濫模塊的某個地方有從一個模塊到另一個模塊的不正當的需求你要求了你不應該要求的
  
  Ocp開閉原則軟件模塊應該是可以不用改動代碼而被擴展的
  其實ocp與其說是一個原則不如說是一個理想它並沒有指出具體的可操作方法而只是給了一個目標
  一些人認為這就意味著類可以繼承這個看法太狹隘了擴展一個模塊固然可以用繼承和override但是用接口組合一樣可以做到關鍵是如果你的模塊依賴抽象的接口而不是具體的類那麼別人就可以很容易通過接口組合adapter decorator什麼的通過給你傳遞不同的接口實現而達到擴展的目的
  這裡面仍然是一個簡單的ask no more在起作用
  
  總而言之所謂面向接口對需求者來說就是用接口定義好自己需要的功能no more no less而所謂多態就是用來實現接口用的工具而已
  完了
  
  以上都是關於需求者的那也是面向接口的主要方面那麼如何約束服務者呢?
  
  封裝啊封裝實際上完全是給服務提供者的工具你可以用它來隱藏自己的實現細節通過最小化對客戶的服務承諾來得到最大的設計彈性
  你要寫一個BankAccount是否要公開所有的內部成員呢?一般可能都不是吧?
  對於這些服務的提供者如果公開了數據成員那麼對用戶的accountbalance = ;這種動作你沒有任何彈性只能老老實實地做field update
  相比於setBalance()後者可以自由地在內部做trace啦或者把職責轉交給內部類啦等等等等靈活得多
  
  那麼為什麼後者靈活呢?因為用方法封裝了field之後我們promise的東西少了我不對客戶承諾我肯定修改我的balance成員變量而是簡單地說我肯定會修改那個邏輯上的balance你再getBalance()就可以得到這個新的值至於我是不是物理上內部有一個balance變量是不是setBalance()就直接去修改這個變量對不起無可奉告我可能沒有也可能有可能今天沒有明天有也可能今天有明天一重構就沒有了
  
  兩者其實都達到了用戶的需求但是後者明顯沒有承諾不必要承諾的實現細節所以根據promise no more的原則封裝後比封裝前好
  
  下面再唠叨一遍靜態工廠
  
  對於類
  java代碼: 
  
   class X implements I{
  }
     public X(){…}
     public static I instance(){return new X();}
   }
  
  下面兩個方法都各自對服務做了什麼承諾呢?
  jav
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25924.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.