Python 里沒有介面,如何寫設計模式?
最近在學設計模式,正在看《大話設計模式》和《深入淺出設計模式》(就是head first那本)
一本用的是C#,一本用JAVA。都有介面。(當一個類實現介面的時候,必須把介面裡面的方法都實現一遍。否則會報錯。)(嗯..我知道C#和Java都不支持多重繼承,Python里支持)我想用Python把這些設計模式實現一遍。Python里沒有介面。如何實現設計模式?用多重繼承的方式?
(我不是一定要用interface. 我只是想知道在沒有interface語言里要如何解決。)(問題已經搜索過了 = = 查不到答案才來這兒的,非伸手。。)
不要看java的設計模式教材就覺得搞設計模式就是設計interface。顯然完全不是這樣的。設計模式搞了那麼多東西就是在告訴你如何在各種情況下解耦你的代碼,讓你的代碼在運行時可以互相組合。這就跟兵法一樣。難道有了飛機大炮兵法就沒有用了嗎?
當然了,動態類型語言和函數式語言有自己的模式,他們長得跟四人幫寫的東西不太一樣,因為有些模式已經化作了語法,而有些語法又化作了模式。搞架構切記生搬硬套,這是沒有好結果的。
設計模式就是在給語言打補丁,所以同樣的東西在Java、C#和C++下面搞出來都不一樣呢。C++有些很好的東西python沒有,有些東西C++可以流暢的寫python就只能打補丁了,如果遇到這個問題的人非常多,這樣就產生了新的針對python的模式了
動態類型,first-class function,宏...可以很方便地實現很多模式
Visitor Pattern -&> Generic Functions (Multiple Dispatch)
Factory Pattern -&> Meta Classes, closures Singleton Pattern -&> Meta ClassesIterator Pattern -&> Anonymous Functions (used with Higher Order Functions)
Mediator, Observer -&> Method combination Facade Pattern -&> Modules (Norvig) ...濫用動態特性、高階函數、宏...,很容易導致程序難以維護,並可能有效率陷阱。
Java讓你更精心地做介面設計,當然也有很多是過度設計,,並且原本是可以不那麼「繞」的。。設計模式是為了更好地做介面設計(類、對象、模塊、函數之間的介面),封裝變化,方便擴展。有高級特性的語言,實現起來更直接而已。換個角度來說,也更容易濫用「設計模式」。。關於設計模式和介面,樓上各位說了不少了。我就不參合了。也一直是個容易引起口水的話題。 既然樓主想用Python把這些設計模式實現一遍。我就推薦一個很棒的項目給你,已經有人做過這件事了,而且做的很棒 ,你在用python實現這些設計模式卡殼時,可以參考下別人的做法~
python-patterns ---A collection of design patterns/idioms in Python
http://pypi.python.org/pypi/zope.interface
另外我沒明白,為什麼設計模式必須要依賴Interface?設計模式是用來解決問題的,為啥Java喜歡談設計模式呢?就是因為語言本身限制多多。
舉個例子,比如Strategy pattern, 在Python裡面因為first-class function+動態類型+變長參數和鍵參數的共同作用,顯示的聲明一個公共介面就變得沒有必要了。
參考:Strategy patternThe (lack of) design patterns in Python - Oreillystatic看到這個問題,突然覺得設計模式真是一個很容易被誤解的東西
實際上軟體設計只需要遵循一下原則,就可以設計出非常優雅的結構:
單一職責原則
開放封閉原則里氏替換原則依賴倒置原則介面隔離原則而所謂的設計模式,其實只是為了在特定語言特性中應用這些原則的產物。知道這個,就不會執著於使用設計模式了看看peter norvig的文章,Design Patterns in Dynamic Languages,在一個支持first class function的語言里,大部分設計模式都不見了。
java設計模式這麼重,很大一部分原因是因為語言的表達能力太弱,設計模式本身不是描述業務邏輯的,把業務邏輯隱藏在一個個模式之下,感覺就像在跟這個語言鬥爭。再分享Mark Dominus的一篇文章 The Universe of Discourse : Design patterns of 1972我覺得寫的很好,Java/c++里的很多模式,並不是用來解決特定情境下的recurring problem. 很大一部分模式都是用來彌補語言自己表達能力的不足。你要實現哪種設計模式?我舉兩個簡單的例子,單例和修飾器。單例:重載類的__init__()修飾器:用@另外我感覺有些設計模式是受到語言的限制才出現的,在其他語言中可以很容易地用其他方法解決問題。在Python中,只要類中有介面中的方法,便相當於實現了該介面(這樣或許不準確,因為Python中沒有介面)。你可以試著在創建了類的實例後,動態給該實例加上一個屬性(可以是一個函數),體會一下和Java的區別。
繼承分為「介面繼承」和「實現繼承」。
在編程語言或者 framework 中實現「介面繼承」比較容易,一般保證一定的二進位介面兼容,或者一定的命名規範即可(比如 SICP 中的查表 data-driven)。著名的 Microsoft Component Object Model 和 CORBA 只有介面繼承。
實現「實現繼承」則相對複雜。一般需要在編譯級別支持,所以多為語言本身支持。
擁有「實現繼承」的語言可以通過通過自限的方式模擬「介面繼承」。C++ 實現了完全的「多實現繼承」,所以它可以完全通過自限的方式模擬「多介面繼承」。Java 和 C# 只有「單實現繼承」,如果通過自限的方式只能支持「單介面繼承」,所以 Java 和 C# 引入了特別的 interface。
另外,這個問題里我就不評論 OO 和 design pattern 本身了。已有的某些答案的吐槽其實很不到位(OO 本身還分輕量的 data abstraction 和重量的大繼承樹,還分 class-based 和 prototype-based。吐槽 OO 很難一步到位說清楚)。鴨子模式,你需要實現這個方法的話,就照實現就是了,返回和形參不限制類型,這就是動態類型的優勢。
再固執點,通過多重繼承實現多種方法。
Python的設計模式問題可以參考&
刪除無意義的回答避免誤人子弟。
當用 Python 的時候,我都忘記什麽是設計模式了。
設計模式不是高大上的東西,是前人的實踐經驗,用來彌補語言的「缺陷」,設計模式用得自然就很好,強套就很蹩腳。
另外推薦看看《Ruby設計模式》畢竟 rb 更像 Python.
如何正確地使用設計模式?
動態語言基本不用設計模式,設計模式主要是要繞過靜態語言強類型編譯器判定的,有了duck type就不需要了。動態語言推薦你去看看元編程,就醬
知道Python中介面的表示(實現)的有兩種方法吧1. @范培說的 zope.interface 這個在 twisted用得很多
2. Pyhton中內置的ABC模塊。 這裡有些文檔可以看下http://dev.pocoo.org/~mitsuhiko/PythonBasket.pdf Flash內部用到的
然後這裡有個文章比較的 Deciphering Glyph ::Explaining Why Interfaces Are Great