成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python設計模式:用模式改變軟件設計

開發(fā) 后端
文章介紹了如何在用Python開發(fā)軟件時應用各種設計模式,Python是一種簡單、靈活、高效的原型語言,特別適合于用來理解和掌握設計模式。

在軟件設計領域中,每一個設計模式都系統(tǒng)地命名、解釋和評價了面向對象系統(tǒng)中的一個重要的和可復用的設計。這樣,我們只要搞清楚這些設計模式,就可以完全或者說很大程度上吸收了那些蘊含在模式中的寶貴經(jīng)驗,從而對軟件體系結構有了比較全面的了解。

51CTO推薦閱讀:Python閉包的概念、形式與應用

更加重要的是,這些模式都可以直接用來指導面向對象系統(tǒng)設計中至關重要的對象建模問題,實際工作中一旦遇到具有相同背景的場合,只需要簡單地套用這些模式就可以了,從而省去了很多摸索工作。

經(jīng)典的設計模式MVC

在長期的軟件實踐過程中,人們逐漸總結出了一些實用的設計模式,并將它們應用于具體的軟件系統(tǒng)中,出色地解決了很多設計上的難題。源于Smalltalk,并在Java中得到廣泛應用的模型-視圖-控制器(Model-View-Controller,MVC)模式,是非常經(jīng)典的一個設計模式,通過它你可以更好地理解"模式"這一概念。

MVC模式通常用在開發(fā)人機交互軟件的時候,這類軟件的最大特點就是用戶界面容易改變,例如,當你要擴展一個應用程序的功能時,通常需要修改菜單來反映這種變化。如果用戶界面和核心功能緊緊交織在一起,要建立這樣一個靈活的系統(tǒng)通常是非常困難的,因為很容易產(chǎn)生錯誤。為了更好地開發(fā)這樣的軟件系統(tǒng),系統(tǒng)設計師必須考慮下面兩個因素:

◆用戶界面應該是易于改變的,甚至在運行期間也是有可能改變的;

◆用戶界面的修改或移植不會影響軟件的核心功能代碼。

為了解決這個問題,可以采用將模型(Model)、視圖(View)和控制器(Controller)相分離的思想。在這種設計模式中,模型用來封裝核心數(shù)據(jù)和功能,它獨立于特定的輸出表示和輸入行為,是執(zhí)行某些任務的代碼,至于這些任務以什么形式顯示給用戶,并不是模型所關注的問題。模型只有純粹的功能性接口,也就是一系列的公開方法,這些方法有的是取值方法,讓系統(tǒng)其它部分可以得到模型的內(nèi)部狀態(tài),有的則是置值方法,允許系統(tǒng)的其它部分修改模型的內(nèi)部狀態(tài)。

視圖用來向用戶顯示信息,它獲得來自模型的數(shù)據(jù),決定模型以什么樣的方式展示給用戶。同一個模型可以對應于多個視圖,這樣對于視圖而言,模型就是可重用的代碼。一般來說,模型內(nèi)部必須保留所有對應視圖的相關信息,以便在模型的狀態(tài)發(fā)生改變時,可以通知所有的視圖進行更新。

控制器是和視圖聯(lián)合使用的,它捕捉鼠標移動、鼠標點擊和鍵盤輸入等事件,將其轉化成服務請求,然后再傳給模型或者視圖。整個軟件的用戶是通過控制器來與系統(tǒng)交互的,他通過控制器來操縱模型,從而向模型傳遞數(shù)據(jù),改變模型的狀態(tài),并最后導致視圖的更新。

MVC設計模式將模型、視圖與控制器三個相對獨立的部分分隔開來,這樣可以改變軟件的一個子系統(tǒng)而不至于對其它子系統(tǒng)產(chǎn)生重要影響。例如,在將一個非圖形化用戶界面軟件修改為圖形化用戶界面軟件時,不需要對模型進行修改,而添加一個對新的輸入設備的支持,則通常不會對視圖產(chǎn)生任何影響。應用了MVC設計模式的軟件系統(tǒng),其基本的實現(xiàn)過程是:

1.控制器創(chuàng)建模型;

2.控制器創(chuàng)建一個或多個視圖,并將它們與模型相關聯(lián);

3.控制器負責改變模型的狀態(tài);

4.當模型的狀態(tài)發(fā)生改變時,模型會通知與之相關的視圖進行更新。

如果用UML來表示MVC設計模式,則如圖1所示:

MVC設計模式

#p#

Python與設計模式

盡管設計模式的目標是努力做到與語言的無關性,但事實上許多模式在應用時還是需要依賴于具體實現(xiàn)語言的某些特性,尤其是該語言的對象模型。由于《設計模式》一書采用的是C++和Smalltalk來講述設計模式,因此訪問控制符和靜態(tài)成員方法(類方法)等都可以直接使用,可惜的是這些特性在Python中都無法用到,原因是Python采了與C++完全不同的對象模式。

簡單說來,Python是一種優(yōu)秀的面向對象腳本語言,它具有動態(tài)語義和快速的原型開發(fā)能力,也許在短短的幾分鐘內(nèi),你就可以開發(fā)出使用其它語言可能需要花費幾個小時的原型系統(tǒng)。Python豐富的工具集使得它位于傳統(tǒng)腳本語言(如Tcl、Perl和Scheme)和系統(tǒng)編程語言(如C、C++和Java)之間,既具備了腳本語言的簡單易用性,同時又能夠提供只有系統(tǒng)語言才可能擁有的某些高級特性。

從面向對象角度來看,Python和Smalltalk一樣都采用了完全的面向對象設計思想,其對象模型能夠支持諸如運算符重載、多重繼承等高級概念。但Python在設計時似乎忽略了面向對象的一項基本原則,那就是數(shù)據(jù)隱藏。與C++和Java不同,Python沒有為類定義提供public、protected和private等關鍵字,這就意味著任何人都可以直接修改對象的屬性。Python之所以這么做,也許是為了保證語法上的簡潔性,就像Python的發(fā)明人Guido van Rossum所認為的那樣:"豐富的語法帶來的負擔多于幫助"。但在某些設計模式中,向外界隱藏數(shù)據(jù)和方法都是非常必要的,為此我們不得不利用Python對象模型提供的某些高級特性,來實現(xiàn)某種程度上的隱藏性。

在Python中應用設計模式的一個有利因素是它的動態(tài)類型綁定,也就是說一個對象很少只是一個類的實例,而是可以在運行時動態(tài)改變。在面向對象系統(tǒng)中,接口是一個基本的組成部分,對象只有通過它們的接口才能與外界進行交互。

對象的接口與其功能是完全分離的,支持相同請求的不同對象針對同一請求所觸發(fā)的操作可能完全不同,這就是動態(tài)綁定的概念。動態(tài)綁定雖然看起來在一定程度上使得代碼不同那么容易理解和維護,但它的確可以使整個軟件系統(tǒng)的結構顯得更加清晰和合理。

作為一門優(yōu)秀的腳本語言,Python正在被越來越多的人所接受,使用Python開發(fā)的項目也越來越多,這也難怪會被大家推崇為"下一代編程語言"中的典型代表。隨著應用范圍的不斷擴展,如何在用Python開發(fā)軟件時充分利用已有的經(jīng)驗和成果將成為人們關注的焦點,而設計模式作為軟件復用的一個重要方面,其價值自然是不言而喻。

可問題是目前所使用的設計模式大都是人們在用Smalltalk、C++和Java開發(fā)軟件時所總結出來的,因此或多或少地帶有這些語言的影子,而要想在Python中使用這些設計模式,必須根據(jù)Python的自身特點和實際需要,靈活地加以運用。

#p#

Python對象模型

對一門具體的編程語言來說,在應用設計模式時影響最大的莫過于它的對象模型了,這是因為大部分設計模式都源自于C++和Java這類面向對象編程語言。要想在Python中復用這些設計模式,首先需要對Python的對象模型有一個比較清晰的認識。

1.類

同其它面向對象編程語言一樣,Python中的類也是一種用戶自定義的數(shù)據(jù)類型,其基本的語法格式是:

  1. class <name>(superclass, ...):  # 定義類  
  2.   data = value   # 共享的類變量  
  3.   def method(self, ...):  # 類中的方法  
  4. self.member = value  # 實例的數(shù)據(jù) 

類定義從關鍵字class開始,并包含整個縮進代碼塊,類中定義的方法和屬性構成了類的名字空間(name space)。一個類通常會有多個方法,它們都以關鍵字def開頭,并且第一個參數(shù)通常都是self,Python中的變量self相當于C++中的關鍵字this,其作用是傳遞一個對象的引用。Python中的類屬性位于類的名字空間中,可以被所有的類實例所共享,這一點同C++和Java相同。訪問類屬性時不需要事先創(chuàng)建類的實例,直接使用類名就可以了。例如:

  1. >>> class Friend:  
  2. default_age = 20 
  3. >>> Friend.default_age  
  4. 20 

除了自定義的類屬性外,Python中的每個類其實都具有一些特殊的類屬性,它們都是由Python的對象模型所提供的。表1列出了這些類屬性:

表1

2.實例

定義類的目的是為了創(chuàng)建它的實例,從面向對象的角度看,類是對數(shù)據(jù)及其相關操作的封裝,而類實例則是對現(xiàn)實生活中某個實體的抽象。假設定義了如下一個類:

  1. class School:  
  2.   def __init__(self, name):  
  3.  self.name = name  
  4.  self.students = []  
  5.   def addStudent(self, student):  
  6.  self.students.append(student) 

要創(chuàng)建School類的一個實例,可以執(zhí)行下面的語句:

  1. bit = School("Beijing Institute of Technology") 
  2.  

在C++和Java中創(chuàng)建類實例時,與類具有相同名稱的構造函數(shù)被調(diào)用,而在Python中創(chuàng)建一個類的實例時,將調(diào)用名為__init__的特殊方法。Python中的類實例繼承了類的所有方法和屬性,并且有自己獨立的名字空間,使用下面的方法可以訪問類實例的方法和屬性:

  1. bit.addStudent("gary")  
  2. bit.students 

Python中的對象屬性有一個非常有趣的地方,那就是使用它們之前不用像C++和Java那樣,必須先在類中進行聲明,因為這些都是可以動態(tài)創(chuàng)建的。作為一門動態(tài)類型語言,Python的這一特性的確非常靈活,但有時也難免產(chǎn)生問題。

例如在許多針對接口的設計模式中,通常都需要知道對象所屬的類,以便能夠調(diào)用不同的實現(xiàn)方法,這些在C++和Java這些強類型語言的對象模型中不難實現(xiàn),但對Python來講可就不那么簡單了,因為Python中的每個變量事實上都沒有固定的類型。

為了解決這一問題,Python的__builtin__模塊提供了兩個非常實用的內(nèi)建函數(shù):isinstance()和issubclass()。其中函數(shù)isinstance()用于測試一個對象是否是某個類的實例,如果是的話則返回1否則返回0。其基本的語法格式是:

  1. isinstance (instance_object, class_object)
  2.  

例如:

  1. >>> class Test:  
  2. pass  
  3. >>> inst = Test()  
  4. >>> isinstance(inst, Test)  

而函數(shù)issubclass()則用于測試一個類是否是另一個類的子類,如果是的話則返回1,否則返回0。其基本的語法格式是:

  1. issubclass(classobj1, classobj2)
  2.  

例如:

  1. >>> class TestA:  
  2.  pass  
  3. >>> class TestB(TestA):  
  4.  pass  
  5. >>> issubclass(TestA, TestB)  
  6. 0  
  7. >>> issubclass(TestB, TestA)  

和類一樣,Python中的每個類實例也具有一些特殊的屬性,它們都是由Python的對象模型所提供的。表2列出了這些屬性:

表2

3.繼承

在面向對象的程序設計中,繼承(Inheritance)允許子類從父類那里獲得屬性和方法,同時子類可以添加或者重載其父類中的任何方法。在Python中定義繼承類的語法格式是:

  1. class <name>(superclass, superclass, ...)  
  2. suit 

例如,對于下面這個類:

  1. class Employee:  
  2.   def __init__(self, name, salary = 0):  
  3.  self.name = name  
  4.  self.salary = salary  
  5.   def raisesalary(self, percent):  
  6.  selfself.salary = self.salary  * (1 + percent)  
  7.   def work(self):  
  8.   print self.name, "writes computer code" 

可以為其定義如下的子類:

  1. class Designer(Employee):  
  2.   def __init__(self, name):  
  3.   Employee.__init__(self, name, 5000)  
  4.   def work(self):  
  5.   print self.name, "writes design document" 

在C++和Java的對象模型中,子類的構造函數(shù)會自動調(diào)用父類的構造函數(shù),但在Python中卻不是這樣,你必須在子類中顯示調(diào)用父類的構造函數(shù),這就是為什么在Designer. __init__方法中必須調(diào)用Employee.__init__方法的原因。

人們對多重繼承的看法一直褒貶不一,C++對象模型允許多重繼承,而Java對象模型則是通過接口(Interface)來間接實現(xiàn)多重繼承的。在對多重繼承的處理上,Python采用了和C++類似的方法,即允許多重繼承,例如:

  1. class A:  
  2.   pass  
  3. class B(A):  
  4.   pass  
  5. class C:  
  6.   pass  
  7. class D(B, C):  
  8.   pass 

4.多態(tài)

嚴格說來,像C++和Java這些強類型語言對象模型中的多態(tài)概念并不適用于Python,因為Python沒有提供類型聲明機制。但由于Python本身是一種動態(tài)類型語言,允許將任意值賦給任何一個變量,如果我們對多態(tài)的概念稍加擴充,將其理解為具有能同時處理多種數(shù)據(jù)類型的函數(shù)或方法,那么Python對象模型實際上也支持經(jīng)過弱化后的多態(tài)。

Python直到代碼運行之時才去決定一個變量所屬的類型,這一特性稱為運行時綁定(runtime binding)。Python解析器內(nèi)部雖然也對變量進行類型分配,但卻十分模糊,并且只有在真正使用它們時才隱式地分配類型。例如,如果程序調(diào)用abs(num),則除數(shù)字之外的任何類型對變量num都沒有意義,此時變量num事實上就進行了非正式的類型分配。

能夠處理不同抽象層次的對象,是面向對象編程最重要的特性之一,也是Python的一個非常重要的組成部分。下面的例子示范了如何讓Python中的一個函數(shù)能夠同時處理多種類型的數(shù)據(jù),在C++的對象模型中,這種多態(tài)被稱為方法重載。

  1. class Polymorph:  
  2.   def deal_int(self, arg):  
  3.   print '%d is an integer' % arg  
  4.   def deal_str(self, arg):  
  5.   print '%s is a string' % arg  
  6.   def deal(self, arg):  
  7.  if type(arg) == type(1):  
  8. self.deal_int(arg)  
  9.  elif type(arg) == type(' '):  
  10. self.deal_str(arg)  
  11.  else:  
  12. print '%s is not an integer or a string' % arg 

這樣,Polymorph類中的方法deal就可以同時處理數(shù)字和字符串了:

  1. >>> p = Polymorph()  
  2. >>> p.deal(100)  
  3. 100 is an integer  
  4. >>> p.deal("Hello World!")  
  5. Hello World! is a string 

#p#

可見性

Python對象模型對可見性的處理與C++和Java完全不同。在C++和Java中,如果屬性或者方法被聲明為private,那就意味著它們只能在類中被訪問,而如果被聲明為protected,則只有該類或者其子類中的代碼能夠訪問這些屬性和方法。但在Python對象模型中,所有屬性和方法都是public的,也就是說數(shù)據(jù)沒有做相應的保護,你可以在任何地方對它們進行任意的修改。

能夠對可見性進行約束是面向對象編程的一個重要特點,其目的是使對象具有優(yōu)良的封裝性:對象僅僅向外界提供訪問接口,而內(nèi)部實現(xiàn)細節(jié)則被很好地隱藏起來。奇怪的是作為一門面向對象腳本語言,Python并沒有提供對可見性進行約束的機制,所有屬性和方法對任何人都是可見的,任何人想知道對象的內(nèi)部實現(xiàn)細節(jié)都是可能的。雖然這樣做能夠帶來部分效率上的優(yōu)化,但卻無法阻止其它程序員對已經(jīng)封裝好的類進行破壞,從某種程度上這不得不說是Python帶給我們的一絲的缺憾。

直到Python 1.5,Guido才引入了名字壓縮(name mangling)的概念,使得類中的一些屬性得以局部化。在進行定義類時,如果一個屬性的名稱是以兩個下劃線開始,同時又不是以下劃線結束的,那么它在編譯時將自動地被改寫為類名加上屬性名。例如:

  1. class Greeting:  
  2. __data = "Hello World!" 
  3. def __init__(self, str):  
  4. Greeting.__data = str 
  5. >>> g = Greeting("Hello Gary!")  
  6. >>> dir (g)  
  7. ['_Greeting__data', '__doc__', '__init__', '__module__'] 

從上面的顯示結果可以看出,Greeting類的屬性__data變成了_Greeting__data。雖然這樣仍然無法阻止外界對它的訪問,但的確使得訪問變得不再那么直接了,從而在一定程序上保護了類中的數(shù)據(jù)不被外界破壞。

在Python中應用設計模式

◆創(chuàng)建型模式描述怎樣創(chuàng)建一個對象,以及如何隱藏對象創(chuàng)建的細節(jié),從而使得程序代碼不依賴于具體的對象,這樣在增加一個新的對象時對代碼的改動非常小。
 
◆結構型模式描述類和對象之間如何進行有效的組織,形成良好的軟件體系結構,主要的方法是使用繼承關系來組織各個類。
 
◆行為型模式描述類或對象之間如何交互以及如何分配職責,實際上它所牽涉的不僅僅是類或對象的設計模式,還有它們之間的通訊模式。
 
這些設計模式如果能夠在Python中直接應用的話,對所有Python程序員來講毫無疑問將是一筆非常寶貴的財富,因為它們的正確性和有效性已經(jīng)被無數(shù)次的實踐所驗證過了。如果想在Python中靈活地運行這些設計模式,可以遵循下面的幾個步驟:

(1)接受設計模式
 
(2)識別設計模式

(3)運用設計模式

首先,你應該認識到設計模式的確能夠改善你所設計的軟件。其次,你必須仔細研究每一種設計模式,學習如何在Python中應用這些模式,以便在今后需要時能夠用到它們。最后,你要努力做到對各個設計模式都有非常清晰的認識,最好能夠形成自己的獨到見解,清楚哪個模式能夠解決哪個設計上的問題,并將它們真正應用到你用Python開發(fā)的軟件中去。所有的設計模式都來源于實踐,最終也將付諸于實踐,只有通過實踐中你才可能掌握每個模式的精髓所在。

小結

設計模式就是解決軟件開發(fā)和設計過程中某個特定問題的特定方法,它最初起源于建筑設計,目前已經(jīng)被廣泛地應用在軟件開發(fā)領域中。設計模式是軟件復用的一種特定形式,理論上它與具體的語言無關,但實際應用時通常會依賴于語言所提供的某些特性。

Python是一門優(yōu)秀的面向對象腳本語言,它的對象模型會影響到部分設計模式的實現(xiàn)。設計模式按其目的可以被劃分成不同的種類,分別用于解決不同方面的實際問題。

【編輯推薦】

  1. 旁觀者清 Python與Ruby各有千秋
  2. 解讀Python內(nèi)存管理機制
  3. Python閉包的概念、形式與應用
  4. 使用Python輕松收集Web站點數(shù)據(jù)
  5. PHP資深開發(fā)者談:緣何放棄PHP改用Python
責任編輯:王曉東 來源: IBM DW
相關推薦

2019-08-12 14:45:50

軟件設計Java

2023-10-19 13:43:00

設計模式軟件設計

2021-10-15 10:05:25

人工智能機器學習技術

2011-07-14 14:46:46

設計模式

2013-06-07 11:31:36

面向對象設計模式

2011-07-21 14:33:02

設計模式

2020-05-19 10:36:28

人工智能AI軟件開發(fā)

2022-09-19 06:25:14

設計模式GoF

2021-02-01 10:01:58

設計模式 Java單例模式

2023-12-12 11:09:55

模板方法模式python設計模式

2023-11-02 21:11:11

JavaScript設計模式

2010-12-27 10:03:29

軟件設計師

2023-12-13 13:28:16

裝飾器模式Python設計模式

2019-08-14 16:56:38

Python職責模式請假

2011-07-29 17:52:13

云計算軟件業(yè)

2022-02-16 07:32:10

性能代碼編程

2020-08-21 07:23:50

工廠模式設計

2020-11-04 08:54:54

狀態(tài)模式

2023-04-10 09:20:13

設計模式訪客模式

2013-11-26 16:09:34

Android設計模式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品区 | 午夜视频在线免费观看 | 久久久久中文字幕 | 九九热九九 | 伊人伊成久久人综合网站 | www国产成人免费观看视频 | 久久99国产精品 | 亚洲欧美在线一区 | 一区二区三区中文字幕 | 中文字幕一区二区三区四区五区 | 国产乱码精品1区2区3区 | 黄色网址在线免费观看 | 亚洲精品一区二区三区蜜桃久 | 亚洲综合一区二区三区 | av影音资源 | 国产午夜精品久久久 | 亚州精品天堂中文字幕 | 日本免费一区二区三区 | 成人av免费看 | 91免费在线视频 | 国产精品区一区二区三 | 欧美日韩国产高清 | 精品国产乱码一区二区三 | 国产精品国产三级国产aⅴ无密码 | 四虎影院在线观看av | 伊人久操| 日本一区二区高清视频 | 国产成人免费视频网站高清观看视频 | 中文字幕色站 | 中文字幕日韩一区 | 99久久久久久99国产精品免 | 成人亚洲网站 | 久久国产精品久久国产精品 | 黄色免费观看 | 亚洲国产成人精品女人久久久 | 国产情侣一区 | 精品成人免费一区二区在线播放 | 日韩国产三区 | 久久精品欧美一区二区三区不卡 | 国产成人免费一区二区60岁 | 伊人精品|