Python 里沒有介面,如何寫設計模式?

所有的duck typing的編程語言都不需要設計模式。

《設計模式》你看看是有幫助的,

但是想在Python中使用就很沒必要。


建議你先看看《黑客與畫家》,語言都是分Level的,按照語言能力大致從C、C++、Java、PHP、Ruby Python、Lisp這樣排列。paul grm聲稱Lisp內置實現了17種設計模式。設計模式並不是優雅的編程,主要作用是為了彌補語言本身的不足。


下次遇到類似問題, 直接github搜 design pattern , 然後語言選python.


用靜態語言的設計模式套Python這樣的動態語言說真的你被禁錮了思維。Python可以很簡單的反射,可以不用面向對象簡易的完成「多態」。


使用zope.interface

from zope.interface import Interface, implements
class IMan:
def talk(self):
"""comments"""

class Geek():
implements(IMan)
def talk(self):
print "知了知了你別吵, 怪蜀黍正在睡午覺"

or

@implementer(IMan):
class Geek():
def talk(self):
print "知了知了你別吵, 怪蜀黍正在睡午覺"

參考信息: https://pypi.python.org/pypi/zope.interface


由於Python具有函數式特徵,大多數設計模式實際上已經沒有必要了!

在必須用到設計模式的時候,比如說給前人的坑爹代碼填坑,也很簡單。由於Python是動態類型的語言,不需要顯式地定義介面,直接把包含所需方法的對象傳進去就可以了。


如果你一定要寫,可以看看《精通Python設計模式》,然後如果覺得很麻煩,可以看我專欄


複製一段話

事實說明,「面向對象」這整個概念基本是錯誤的。它的風靡是因為當初的「軟體危機」(天知道是不是真的存在這危機)。 設計的初衷是讓「界面」和「實現」分離,從而使得下層實現的改動不影響上層的功能。可是大部分面向對象語言的設計都遵循一個根本錯誤的原則:「所有的東西 都是對象(Everything is an object)。」以至於所有的函數都必須放在所謂的「對象」裡面,而不能直接被作為參數或者變數傳遞。這導致很多時候需要使用繁瑣的設計模式(design patterns) 來達到甚至對於C 語言都直接了當的事情。而其實「界面」和「實現」的分離,並不需要把所有函數都放進對象里。另外的一些概念,比如繼承,重載,其實帶來的問題比它們解決的 還要多。

「面向對象方法」的過度使用,已經開始引起對整個業界的負面作用。很多公司里的程序員喜歡生搬硬套一些不必要的設計模式,其實什麼好事情也沒幹,只是使得程序冗長難懂。

那 么如何看待具備高階函數的面向對象語言,比如Python, JavaScript, Ruby, Scala? 當然有了高階函數,你可以直截了當的表示很多東西,而不需要使用設計模式。但是由於設計模式思想的流毒,一些程序員居然在這些不需要設計模式的語言里也採用繁瑣的設計模式,讓人哭笑不得。所以在學習的時候,最好不要用這些語言,以免受到不必要的干擾。到時候必要的時候再回來使用它們,就可以取其精華,去其糟粕。

關於作者: http://www.zhihu.com/topic/19587684

原文已經刪除,這裡 http://www.douban.com/group/topic/35512747/ 或者RSS裡面可以看到原文


現在設計模式教學有一個很嚴重的問題就是跳不出java和uml類圖。誠然,uml是個比較通用也比較清晰描述對象關係的圖語言,但是很容易讓學生就認為設計模式就一定要按照那樣的類和介面去實現。其實設計模式是一種思想,面向對象也是一種思想。舉個最簡單的例子,單例模式java里很喜歡 public static XX getInstance() ,但我不這麼寫可以嗎?當然可以,只要滿足你在該進程內能用某種方式保證當前對象實例最多為一個的,那麼這種思想都可以叫單例模式,而不是一定要按照那段demo寫下來。

面向對象不等於設計模式,實際上java的面向對象還不算全面,Python Ruby這類語言基本貫徹著一切皆對象的思想,Ruby我不熟,以Python為例。你知道Python的函數、代碼、類型等只要你想得到需要實現的概念都是對象嗎?你知道Python 連用C寫的源碼都在貫徹一切皆對象這個思想嗎?

這裡我十分同意 @劉啟明 的回答,題主應該跳出這些條條框框,認清OOP本質。重要的是多實踐多參與項目,多讀讀優秀的代碼,你就會慢慢知道哪些問題在我們的工作中是會遇到可以通過代碼設計避免的。屆時再回過頭來,你會發現你不知不覺理所當然地用了很多類似設計模式的思想,但不會再局限於幾個類的uml了。


可以參考這本書

Python
inPractice: Create Better Programs Using Concurrency, Libraries, and Patterns


1.誰特么說動態語言沒設計模式的,亂扯

2.python裡面還有一個更好玩的,更實用的,元編程,我可以根據一組參數(或者配置文件)組裝出我自定義功能更強大的類,自己來控制類對象的生成

3.設計模式里比代碼更重要的是解決某類問題的思想,程序裡面有好些東西是相通的,比如觀察者模式就是我很喜歡的一種模式,用這種模式來套用,寫代碼,可以很方便的來做不同組件之間的通知,以及消息的訂閱,推送

4.設計模式的存在只是為了更漂亮的組裝代碼,你代碼量沒到一定量的時候很難體會到設計模式的好,可以看看一些優秀的開源框架,裡面肯定有不少設計模式的影子,不會寫就看看別人怎麼寫的


設計模式是獨立語言的,python的繼承機制也可以很方便地實現各種設計模式。我們以單例模式為例。

假定業務代碼中需要維護一堆配置數據,這些數據是由其他對象共享的,那麼這個配置數據應該只保存一份。這裡用單例模式,可以使你的代碼很清晰。

單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點

單例模式實現代碼如下:

# 類文件名為basic_class.py
class Singleton(type):
_instances = {}

def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]

class DataHolder(object):
__metaclass__ = Singleton
__shared_state = {}

def __init__(self):
self.__dict__ = self.__shared_state

定義好DataHolder之後,app.py初始化時定義一個DataHolder對象dh,並填入一些初始化配置

# 程序入口app.py
dh = basic_class.DataHolder()
dh.system_settings = env
dh.sms_last_submit_time = 0
...

在其他的文件中在定義dh時,得到的將是同一份配置數據,並且可以修改數據

# update_config.py
dh = basic_class.DataHolder()
# submit_time is retrieved from database
dh.sms_last_submit_time = max(submit_time, dh.sms_last_submit_time)
# other code

basic_class.py中單例模式的寫法

1. "class Singleton(type)", type是用來構造類的,Singleton繼承type,所以也可以用來生成類。type()的解釋如下:type(name, bases, dict)。

2. Singleton中定義字典 _instances用來存儲所有的信息,__call__方法實現了單例邏輯,以構造的類的名字為key,添加到_instances中。

3. "__metaclass__ = Singleton",類DataHolder指定生成方式是Singleton。


介面的出現是為了解決強類型語言中,不同類型參數需要不同的方法進行重載的問題,介面更為清楚的描述了各個類和方法之間的關係。duck typy語言由於其本身特性,不需要方法重載,所以不需要介面來幫助實現。


python設計模式 可在線運行代碼python設計模式


有duck type的動態語言,都沒有java里介面的必要,天生就是面向介面編程, 所以很多設計模式在這些語言面前就不這麼適用了


這個是因為因為JAVA語言本身太渣,才需要無處不在的設計模式,Python不需要


題主覺得哪兒個模式在python下不能用?


設計模式是解決某類編程問題的範式,從這個角度來講設計模式是語言無關的。


1、如果你想在python達到「 (當一個類實現介面的時候,必須把介面裡面的方法都實現一遍。否則會報錯。) 」這樣的效果,你可以使用python的abc模塊

2、另一種方式是使用 zope.inteface 這個包

python設計模式推薦閱讀:

精通python設計模式

Python編程實戰 運用設計模式、並發和程序庫創建高質量程序

faif/python-patterns

二十三種設計模式及其python實現 - 李瓊羽 - 博客園

《大話設計模式》Python版代碼實現 - 五嶽 - 博客園

小明明s Github - 設計模式

設計模式六大原則 - 自己動手寫程序,勿好高騖遠 - 博客頻道 - CSDN.NET


設計模式是面向對象編程組織代碼的形式。應該脫離具體的編程語言。

更多的注意力應該放在模式的定義,運用場景和設計思路上。

舉個例子,單例模式。

定義,一個類,無論被new幾次,返回的都是同一個對象。

你只要寫出一個類,它能達到同樣的效果就是單例。

場景,前端的登陸框。一些全局的管理器。

設計思路,判斷類是否被調用過。沒調用過就生成一個對象。找個地方把這個對象存起來。下次調用直接返回該對象。


設計模式只是思想,不要局限語


也是搜索python的介面相關問題找到這裡來的,把我找到的有價值部分答在這裡吧。

直接回答題主問題的部分大致如下:

細節請參考python的介面和抽象類這篇文章,我比較認同文中使用ABCMeta來模擬interface的做法。大致就是用metaclass機制來做出一個特別的class,它可以在語義上模擬像
Java這類語言中的interface, 達到讓這個像interface的class可以明確的約束其子類可以或者必須實現什麼樣的成員函數,同時又不暴露更多的子類細節給基類對象的持有者這兩個關鍵的目的。

以下是個人對於設計模式以及介面的相關理解,也許有助於題主:

設計模式中的「介面」是一種概念化的東西,並不直接等價於Java中的interface或者C++中的抽象類這些語言 級別的特性(反倒是這些語言級別的特性正是語言設計者為了迎合OO和設計模式中的介面概念而產生的,因此不同語言的實際設計結果不盡相同)。雖然題主其實已經表達了自己明白這個差別的意思,容再補充一些細節。介面這個概念最核心的部分我覺得有兩個,一個是對實現細節的隱藏,另一個就是對所有聲稱實現了介面的實體進行強制約束。只要任何機制達到了這兩個目的,就可以認為是一種「介面」。設計模式中之所有要大量使用介面的概念,正是因為許多設計模式的目標之一就是要隱藏不必要的實現細節從而解耦, 同時提供一種程序員之間的方便的概念層協議來統一交流術語並一致的實現契約。

回來Python上來(本人對Python其實不甚了了,有謬誤之處見諒),我覺得Python中比OO更核心的自省機制使得interface要求的信息隱藏能力在單純的繼承機制下無法完美實現,總是容易通過自省機制探查到介面想隱藏的那部分細節。從而在語言級別想要直接支持interface容易產生複雜的特殊設計規則。那退而求其次的辦法就是允許模擬之。之所以把metaclass機製做出來的這個稱為「模擬」,因為這樣的代碼要求特殊處理一些 元函數(從而一定程度上限制了interface class本身的metaclass能力,或者說對更基本的語言級功能產生了侵入),還不能在編譯期報告不符合介面規範的情況,並且看起來總是有些彆扭,生硬。


別看設計模式了,浪費時間!


這個地方是由於python不同於其他高級語言,具備強制類型的原因。python中一切都是對象,可以指向任何類型,完全可以定義某個對象,使其實現類似interface的功能,然後成為其他類的父類;要知道python是支持多重繼承的。


推薦閱讀:

TAG:Python | 設計模式 |

分頁阅读: 1 2