Python設(shè)計(jì)模式-用模式改變軟件設(shè)計(jì)_第1頁
Python設(shè)計(jì)模式-用模式改變軟件設(shè)計(jì)_第2頁
Python設(shè)計(jì)模式-用模式改變軟件設(shè)計(jì)_第3頁
Python設(shè)計(jì)模式-用模式改變軟件設(shè)計(jì)_第4頁
Python設(shè)計(jì)模式-用模式改變軟件設(shè)計(jì)_第5頁
已閱讀5頁,還剩19頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

在軟件設(shè)計(jì)領(lǐng)域中,每一個(gè)設(shè)計(jì)模式都系統(tǒng)地命名、解釋和評(píng)價(jià)了面向?qū)ο笙到y(tǒng)中的一個(gè)重要的和可復(fù)用的設(shè)計(jì)。這樣,我們只要搞清楚這些設(shè)計(jì)模式,就可以完全或者說很大程度上吸收了那些蘊(yùn)含在模式中的寶貴經(jīng)驗(yàn),從而對(duì)軟件體系結(jié)構(gòu)有了比較全面的了解。51CTO推薦閱讀:Python閉包的概念、形式與應(yīng)用更加重要的是,這些模式都可以直接用來指導(dǎo)面向?qū)ο笙到y(tǒng)設(shè)計(jì)中至關(guān)重要的對(duì)象建模問題,實(shí)際工作中一旦遇到具有相同背景的場(chǎng)合,只需要簡(jiǎn)單地套用這些模式就可以了,從而省去了很多摸索工作。在長(zhǎng)期的軟件實(shí)踐過程中,人們逐漸總結(jié)出了一些實(shí)用的設(shè)計(jì)模式,并將它們應(yīng)用于具體的軟件系統(tǒng)中,出色地解決了很多設(shè)計(jì)上的難題。源于Smalltalk,并在Java中得到廣泛應(yīng)用的模型-視圖-控制器(Model-View-Controller,MVC)模式,是非常經(jīng)典的一個(gè)設(shè)計(jì)模式,通過它你可以更好地理解"模式"這一概念。MVC模式通常用在開發(fā)人機(jī)交互軟件的時(shí)候,這類軟件的最大特點(diǎn)就是用戶界面容易改變,例如,當(dāng)你要擴(kuò)展一個(gè)應(yīng)用程序的功能時(shí),通常需要修改菜單來反映這種變化。如果用戶界面和核心功能緊緊交織在一起,要建立這樣一個(gè)靈活的系統(tǒng)通常是非常困難的,因?yàn)楹苋菀桩a(chǎn)生錯(cuò)誤。為了更好地開發(fā)這樣的軟件系統(tǒng),系統(tǒng)設(shè)計(jì)師必須考慮下面兩個(gè)因素:◆用戶界面應(yīng)該是易于改變的,甚至在運(yùn)行期間也是有可能改變的;◆用戶界面的修改或移植不會(huì)影響軟件的核心功能代碼。.專業(yè).專注. 為了解決這個(gè)問題,可以采用將模型(Model)、視圖(View)和控制器 (Controller)相分離的思想。在這種設(shè)計(jì)模式中,模型用來封裝核心數(shù)據(jù)和功能,它獨(dú)立于特定的輸出表示和輸入行為,是執(zhí)行某些任務(wù)的代碼,至于這些任務(wù)以什么形式顯示給用戶,并不是模型所關(guān)注的問題。模型只有純粹的功能性接口,也就是一系列的公開方法,這些方法有的是取值方法,讓系統(tǒng)其它部分可以得到模型的內(nèi)部狀態(tài),有的則是置值方法,允許系統(tǒng)的其它部分修改模型的內(nèi)部狀態(tài)。視圖用來向用戶顯示信息,它獲得來自模型的數(shù)據(jù),決定模型以什么樣的方式展示給個(gè)視圖,這樣對(duì)于視圖而言,模型就是可重用的代碼。一般來說,模型內(nèi)部必須保留所有對(duì)應(yīng)視圖的相關(guān)信息,以便在模型的狀態(tài)發(fā)生改變時(shí),可以通知所有的視圖進(jìn)行更新。鼠標(biāo)點(diǎn)擊和鍵盤輸入等事件,將其轉(zhuǎn)化成服務(wù)請(qǐng)求,然后再傳給模型或者視圖。整個(gè)軟件的用戶是通過控制器來與系統(tǒng)交互的,他通過控制器來操縱模型,從而向模型傳遞數(shù)據(jù),改變模型的狀態(tài),并最后導(dǎo)致視圖的更新。MVC設(shè)計(jì)模式將模型、視圖與控制器三個(gè)相對(duì)獨(dú)立的部分分隔開來,這樣可以改變軟件的一個(gè)子系統(tǒng)而不至于對(duì)其它子系統(tǒng)產(chǎn)生重要影響。例如,在將一個(gè)非圖形化用戶界面軟件修改為圖形化用戶界面軟件時(shí),不需要對(duì)模型進(jìn)行修改,而添加一個(gè)對(duì)新的輸入設(shè)備的支持,則通常不會(huì)對(duì)視圖產(chǎn)生任何影響。應(yīng)用了MVC設(shè)計(jì)模式的軟件系統(tǒng),其基本的實(shí)現(xiàn)過程是:1.控制器創(chuàng)建模型;2.控制器創(chuàng)建一個(gè)或多個(gè)視圖,并將它們與模型相關(guān)聯(lián);.專業(yè).專注..word可編輯.3.控制器負(fù)責(zé)改變模型的狀態(tài);4.當(dāng)模型的狀態(tài)發(fā)生改變時(shí),模型會(huì)通知與之相關(guān)的視圖進(jìn)行更新。UML表示MVC設(shè)計(jì)模式,則如圖1所示:Python與設(shè)計(jì)模式盡管設(shè)計(jì)模式的目標(biāo)是努力做到與語言的無關(guān)性,但事實(shí)上許多模式在應(yīng)用時(shí)還是需的某些特性,尤其是該語言的對(duì)象模型。由于《設(shè)計(jì)模式》一書采用的是C++和Smalltalk來講述設(shè)計(jì)模式,因此訪問控制符和靜態(tài)成員方法(類方法)等都可以直接使用,可惜的是這些特性在Python中都無法用到,原因是Python采了與C++完全不同的對(duì)象模式。.專業(yè).專注. 簡(jiǎn)單說來,Python是一種優(yōu)秀的面向?qū)ο竽_本語言,它具有動(dòng)態(tài)語義和快速的原型開發(fā)能力,也許在短短的幾分鐘內(nèi),你就可以開發(fā)出使用其它語言可能需要花費(fèi)幾個(gè)小時(shí)的統(tǒng)編程語言(如C、C++和Java)之間,既具備了腳本語言的簡(jiǎn)單易用性,同時(shí)又能夠提供只有系統(tǒng)語言才可能擁有的某些高級(jí)特性。從面向?qū)ο蠼嵌葋砜矗琍ython和Smalltalk一樣都采用了完全的面向?qū)ο笤O(shè)計(jì)思想,其對(duì)象模型能夠支持諸如運(yùn)算符重載、多重繼承等高級(jí)概念。但Python在設(shè)計(jì)時(shí)似乎忽略了面向?qū)ο蟮囊豁?xiàng)基本原則,那就是數(shù)據(jù)隱藏。與C++和Java不同,Python沒有為類定GuidovanRossum所認(rèn)為的那樣:"豐富的語法帶來的負(fù)擔(dān)多于幫助"。但在某些設(shè)計(jì)模式中,向外界隱藏?cái)?shù)據(jù)和方法都是非常必要的,為此我們不得不利用Python對(duì)象模型提供的某些高級(jí)特性,來實(shí)現(xiàn)某種程度上的隱藏性。在Python中應(yīng)用設(shè)計(jì)模式的一個(gè)有利因素是它的動(dòng)態(tài)類型綁定,也就是說一個(gè)對(duì)象很少只是一個(gè)類的實(shí)例,而是可以在運(yùn)行時(shí)動(dòng)態(tài)改變。在面向?qū)ο笙到y(tǒng)中,接口是一個(gè)基本的組成部分,對(duì)象只有通過它們的接口才能與外界進(jìn)行交互。對(duì)象的接口與其功能是完全分離的,支持相同請(qǐng)求的不同對(duì)象針對(duì)同一請(qǐng)求所觸發(fā)的操作可能完全不同,這就是動(dòng)態(tài)綁定的概念。動(dòng)態(tài)綁定雖然看起來在一定程度上使得代碼不同那么容易理解和維護(hù),但它的確可以使整個(gè)軟件系統(tǒng)的結(jié)構(gòu)顯得更加清晰和合理。作為一門優(yōu)秀的腳本語言,Python正在被越來越多的人所接受,使用Python開發(fā)的大家推崇為"下一代編程語言"中的典型代表。隨著應(yīng)用范.專業(yè).專注. 圍的不斷擴(kuò)展,如何在用Python開發(fā)軟件時(shí)充分利用已有的經(jīng)驗(yàn)和成果將成為人們關(guān)注的焦點(diǎn),而設(shè)計(jì)模式作為軟件復(fù)用的一個(gè)重要方面,其價(jià)值自然是不言而喻??蓡栴}是目前所使用的設(shè)計(jì)模式大都是人們?cè)谟肧malltalk、C++和Java開發(fā)軟件時(shí)所總結(jié)出來的,因此或多或少地帶有這些語言的影子,而要想在Python中使用這些設(shè)計(jì)模式,必須根據(jù)Python的自身特點(diǎn)和實(shí)際需要,靈活地加以運(yùn)用。Python對(duì)象模型對(duì)一門具體的編程語言來說,在應(yīng)用設(shè)計(jì)模式時(shí)影響最大的莫過于它的對(duì)象模型了,這是因?yàn)榇蟛糠衷O(shè)計(jì)模式都源自于C++和Java這類面向?qū)ο缶幊陶Z言。要想在Python中復(fù)用這些設(shè)計(jì)模式,首先需要對(duì)Python的對(duì)象模型有一個(gè)比較清晰的認(rèn)識(shí)。同其它面向?qū)ο缶幊陶Z言一樣,Python中的類也是一種用戶自定義的數(shù)據(jù)類型,其基本的語法格式是:1.class<name>(superclass,...):#定義類datavalue的類變量defmethodself法selfmembervalue#實(shí)例的數(shù)據(jù)類類定義從關(guān)鍵字class開始,并包含整個(gè)縮進(jìn)代碼塊,類中定義的方法和屬性構(gòu)成了類的名字空間(namespace)。一個(gè)類通常會(huì)有多個(gè)方法,它們都以關(guān)鍵字def開頭,并且第一個(gè)參數(shù)通常都是self,Python中的變量self相當(dāng)于C++中的關(guān)鍵字this,其作用是傳Python共.專業(yè).專注..word可編輯.享,這一點(diǎn)同C++和Java相同。訪問類屬性時(shí)不需要事先創(chuàng)建類的實(shí)例,直接使用類名就可以了。例如:1.>>>classFriend:defaultage3.>>>Friend.default_age.20除了自定義的類屬性外,Python中的每個(gè)類其實(shí)都具有一些特殊的類屬性,它們都是由由Python的對(duì)象模型所提供的。表1列出了這些類屬性:2.實(shí)例定義類的目的是為了創(chuàng)建它的實(shí)例,從面向?qū)ο蟮慕嵌瓤矗愂菍?duì)數(shù)據(jù)及其相關(guān)操作的封裝,而類實(shí)例則是對(duì)現(xiàn)實(shí)生活中某個(gè)實(shí)體的抽象。假設(shè)定義了如下一個(gè)類:finitselfnamee4.self.students=[]fstudentsappendstudent要?jiǎng)?chuàng)建School類的一個(gè)實(shí)例,可以執(zhí)行下面的語句:nstituteofTechnology.專業(yè).專注. 在C++和Java中創(chuàng)建類實(shí)例時(shí),與類具有相同名稱的構(gòu)造函數(shù)被調(diào)用,而在Python有方法和屬性,并且有自己獨(dú)立的名字空間,使用下面的方法可以訪問類實(shí)例的方法和屬性性:Python中的對(duì)象屬性有一個(gè)非常有趣的地方,那就是使用它們之前不用像C++和Java那樣,必須先在類中進(jìn)行聲明,因?yàn)檫@些都是可以動(dòng)態(tài)創(chuàng)建的。作為一門動(dòng)態(tài)類型語言,Python的這一特性的確非常靈活,但有時(shí)也難免產(chǎn)生問題。例如在許多針對(duì)接口的設(shè)計(jì)模式中,通常都需要知道對(duì)象所屬的類,以便能夠調(diào)用不同的實(shí)現(xiàn)方法,這些在C++和Java這些強(qiáng)類型語言的對(duì)象模型中不難實(shí)現(xiàn),但對(duì)Python來講可就不那么簡(jiǎn)單了,因?yàn)镻ython中的每個(gè)變量事實(shí)上都沒有固定的類型。為了解決這一問題,Python的__builtin__模塊提供了兩個(gè)非常實(shí)用的內(nèi)建函數(shù):isinstance()和issubclass()。其中函數(shù)isinstance()用于測(cè)試一個(gè)對(duì)象是否是某個(gè)類的實(shí)例,如果是的話則返回1否則返回0。其基本的語法格式是:bjectclassobject例如:1.>>>classTest:3.>>>inst=Test()4.>>>isinstance(inst,Test)1.專業(yè).專注..word可編輯.而函數(shù)issubclass()則用于測(cè)試一個(gè)類是否是另一個(gè)類的子類,如果是的話則返回1,否則返回0。其基本的語法格式是:classobj例如:1.>>>classTestA:3.>>>classTestB(TestA):pass5.>>>issubclass(TestA,TestB)7.>>>issubclass(TestB,TestA)8.1和類一樣,Python中的每個(gè)類實(shí)例也具有一些特殊的屬性,它們都是由Python的對(duì)象模型所提供的象模型所提供的。表2列出了這些屬性:在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,繼承(Inheritance)允許子類從父類那里獲得屬性和方法,同時(shí)子類可以添加或者重載其父類中的任何方法。在Python中定義繼承類的語法格式是:1.class<name>(superclass,superclass,...)例如,對(duì)于下面這個(gè)類:.專業(yè).專注. definitselfnamesalary=0):eself.salary=salaryelfpercentlfselfsalaryselfsalarypercentkselfselfnamewritescomputercode可以為其定義如下的子類可以為其定義如下的子類:eefinitselfnameployeeinitselfnamedefwork(self):ritesdesigndocument在C++和Java的對(duì)象模型中,子類的構(gòu)造函數(shù)會(huì)自動(dòng)調(diào)用父類的構(gòu)造函數(shù),但在Python中卻不是這樣,你必須在子類中顯示調(diào)用父類的構(gòu)造函數(shù),這就是為什么在Designer.__init__方法中必須調(diào)用Employee.__init__方法的原因。人們對(duì)多重繼承的看法一直褒貶不一,C++對(duì)象模型允許多重繼承,而Java對(duì)象模型則是通過接口(Interface)來間接實(shí)現(xiàn)多重繼承的。在對(duì)多重繼承的處理上,Python采用了和C++類似的方法,即允許多重繼承,例如:passsDBC4.多態(tài).專業(yè).專注. 嚴(yán)格說來,像C++和Java這些強(qiáng)類型語言對(duì)象模型中的多態(tài)概念并不適用于Python,因?yàn)镻ython沒有提供類型聲明機(jī)制。但由于Python本身是一種動(dòng)態(tài)類型語言,允許將任意值賦給任何一個(gè)變量,如果我們對(duì)多態(tài)的概念稍加擴(kuò)充,將其理解為具有能同時(shí)處理多種數(shù)據(jù)類型的函數(shù)或方法,那么Python對(duì)象模型實(shí)際上也支持經(jīng)過弱化后的多態(tài)。Python直到代碼運(yùn)行之時(shí)才去決定一個(gè)變量所屬的類型,這一特性稱為運(yùn)行時(shí)綁定 (runtimebinding)。Python解析器內(nèi)部雖然也對(duì)變量進(jìn)行類型分配,但卻十分模糊,并且只有在真正使用它們時(shí)才隱式地分配類型。例如,如果程序調(diào)用abs(num),則除數(shù)字之外的任何類型對(duì)變量num都沒有意義,此時(shí)變量num事實(shí)上就進(jìn)行了非正式的類型分配。能夠處理不同抽象層次的對(duì)象,是面向?qū)ο缶幊套钪匾奶匦灾唬彩荘ython的一個(gè)非常重要的組成部分。下面的例子示范了如何讓Python中的一個(gè)函數(shù)能夠同時(shí)處理多種類型的數(shù)據(jù),在C++的對(duì)象模型中,這種多態(tài)被稱為方法重載。ealintselfargntdisanintegerargdefdeal_str(self,arg):sastringargselfargtypeargtypeintargeliftypeargtype'):10.self.deal_str(arg)11.else:12.print'%sisnotanintegerorastring'%arg這樣,Polymorph類中的方法deal就可以同時(shí)處理數(shù)字和字符串了:.專業(yè).專注. 2.>>>p.deal(100)r4.>>>p.deal("HelloWorld!")ring可見性ava性或者方法被聲明為private,那就意味著它們只能在類中被訪問,而如果被聲明為protected,則只有該類或者其子類中的代碼能夠訪問這些屬性和方法。但在Python對(duì)象模型中,所有屬性和方法都是public的,也就是說數(shù)據(jù)沒有做相應(yīng)的保護(hù),你可以在任何地方對(duì)它們進(jìn)行任意的修改。能夠?qū)梢娦赃M(jìn)行約束是面向?qū)ο缶幊痰囊粋€(gè)重要特點(diǎn),其目的是使對(duì)象具有優(yōu)良的封裝性:對(duì)象僅僅向外界提供訪問接口,而內(nèi)部實(shí)現(xiàn)細(xì)節(jié)則被很好地隱藏起來。奇怪的是作為一門面向?qū)ο竽_本語言,Python并沒有提供對(duì)可見性進(jìn)行約束的機(jī)制,所有屬性和方法對(duì)任何人都是可見的,任何人想知道對(duì)象的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)都是可能的。雖然這樣做能夠帶來部分效率上的優(yōu)化,但卻無法阻止其它程序員對(duì)已經(jīng)封裝好的類進(jìn)行破壞,從某種程度上這不得不說是Python帶給我們的一絲的缺憾。直到Python1.5,Guido才引入了名字壓縮(namemangling)的概念,使得類中的一些屬性得以局部化。在進(jìn)行定義類時(shí),如果一個(gè)屬性的名稱是以兩個(gè)下劃線開始,同時(shí)又不是以下劃線結(jié)束的,那么它在編譯時(shí)將自動(dòng)地被改寫為類名加上屬性名。例如:2.__data="HelloWorld!"elfstrGreeting.__data=str5.>>>g=Greeting("HelloGary!")6.>>>dir(g)Greetingdata'__doc__','__init__','__module__'].專業(yè).專注. 從上面的顯示結(jié)果可以看出,Greeting類的屬性__data變成了_Greeting__data。雖然這樣仍然無法阻止外界對(duì)它的訪問,但的確使得訪問變得不再那么直接了,從而在一定程序上保護(hù)了類中的數(shù)據(jù)不被外界破壞。在Python中應(yīng)用設(shè)計(jì)模式◆創(chuàng)建型模式描述怎樣創(chuàng)建一個(gè)對(duì)象,以及如何隱藏對(duì)象創(chuàng)建的細(xì)節(jié),從而使得程序代碼不依賴于具體的對(duì)象,這樣在增加一個(gè)新的對(duì)象時(shí)對(duì)代碼的改動(dòng)非常小?!艚Y(jié)構(gòu)型模式描述類

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論