三種面向對象設計思想
簡單來說,本文我將要描述的面向對象編程分三類:
- 純粹面向對象編程(Traditional OOP)
- 由運行時輔助的類型轉換的面向對象編程(Type casting OOP with runtime)
- 由運行時輔助的元數據面向對象編程(Metadata OOP with runtime)。
純粹面向對象編程(Traditional OOP)
代碼 explicit,結構清晰,架構明顯,可維護性最高,但是 large code base(大代碼),實現過程複雜,過程累贅。
如果有抽象支持(虛函數、抽象類、介面)的話,則可以【延遲】實現,讓本應該抽象的類更輕量。
優點:代碼非常緊湊,一切數據結構的交互一目了然。
缺點:實現較大規模的業務將變得困難,開發者在設計介面所在層次有很大困難,同時實現大量的介面將系統變得很複雜。
適合:中小規模、需要長期維護、開發周期允許長、實現需要精鍊的項目
代表:C++(不使用 RTTI),Java(不使用運行時相關調用)
示例:
interface SomeHobby { void sing();}class Person { /* code */ }abstract class PersonWhoHasHobby extends Person implement SomeHobby { /* code */ }class PersonWithHobby implement SomeHobby { void sing() { /* code */ }}// 表演台上表演個人愛好class Playground { private PersonWhoHasHobby person; public Playground(PersonWhoHasHobby person) { this.person = person; } public void performHobbySing() { this.person.sing(); }}Playground pg = new Playground(new PersonWithHobby());pg.performHobbySing();
由運行時輔助的類型轉換的面向對象編程(Type casting OOP with runtime)
代碼 explicit,結構靈活,稍微動態,在 IoC 編碼場合十分便利可直接反射。
抽象方面 instanceof 讓類型確定,dynamic_cast 必須是抽象類或介面。
兩者的目的在於更快地得到介面而不需要擔心介面所處的層級(在對象繼承層級之下或之上)。
這種編程方式運行時起到的只是類型反射,通常用於類型檢查。
優點:開發者不需要編寫大量的介面類(向前轉換類),通過 cast 解決了向後轉換的問題,讓開發者無須擔心介面所在層的問題。
缺點:直接的介面抽出容易導致編碼混亂,過多的類型轉換讓運行變得低效,結構不夠緊湊,容許開發者比較隨意抽離數據,可能產生跟 goto 類似效果。
適合:中大規模、需要持續集成、迭代周期長的項目
代表:C++ with RTTI,Java
示例:
interface SomeHobby { void sing();}class Person { }class PersonWithHobby implement SomeHobby { void sing() { /* code */ }}// 表演台上表演個人愛好class Playground { private Person p; public Playground(Person p) { this.p = p; } public void performHobbySing(Person p) { if (p instanceof PersonWithHobby) { PersonWithHobby pwh = (PersonWithHobby) p; pwh.sing(); } }}Playground pg = new Playground(new PersonWithHobby());pg.performHobbySing();
由運行時輔助的元數據面向對象編程(Metadata OOP with runtime)
代碼 implicit,結構非常靈活,可像橡皮泥一樣隨意變換,支持可產生的對象後天行為,在需要快速抽象編碼場合發揮極大作用。
開發者不需要關心類型問題,一切的東西只要繼承過來就可以通過反射取得,無論數據還是方法。
比如 Python 的 setattr / getattr 可以動態增加對象的元數據,而 Ruby、JavaScript 直接可通過純天然的語法給對象增加元數據。
這種編程在設計上沒有介面概念,一般通過 duck typing 解決。
優點:在於編碼十分自由,開發效率很高。
缺陷:具體實現隱蔽,開發者編寫時需注意非空實現,後期可追溯性差。
適合:中小規模、需要快速開發、開發周期要求短的項目
代表:Python Ruby JavaScript
示例:
class Person # code ...endclass Playground def initialize(p) @person = p end def perform_hobby_sing @person.sing() endendp = Person.newdef p.sing # code ...endpg = Playground.new(p)pg.perform_hobby_sing()
一切的設計模式組合即是對象之間「溝通」的方式,好比齒輪之間的交錯的嚙合。
設計處理這些交錯的嚙合的方式稱為設計模式。
有些語言適合第一種,有些語言適合第二種,有些語言適合第三種,根據不同的項目場景有不同的選擇。
By:Jakit
推薦閱讀:
※1.3 什麼是軟體工程?
※為什麼軟體工程教科書上的內容和現實的軟體項目開發管理之間存在著一定差異?
※3.3 需求模型
※軟體危機の典型癥狀
※《人月神話》讀書筆記④:解決問題