jjhou.928@gmail.com同濟大學軟件學院OOPrinciplesGoF'sDesignPatternsBeyondGoF'sDesignPatterns(ReferenceCounting,PooledAllocation,UndoableinJava)jjhou.928@gmail.com:*花樣,圖案,形態,樣式*服裝裁剪的紙樣,澆鑄用的模具*模範,榜樣,典型()jjhou.928@gmail.com•…•Sharing•Copy-on-Write•EmbeddedPointers•FixedAllocation•VariableAllocation•PooledAllocation•ReferenceCounting•GarbageCollection•VirtualConstructor•Singleton•HeapObjects•SmartPointers•ReferenceCounting•Proxy•DoubleDispatching•Singletons•SmartPointers•ObjectFactories•AbstractFactories•Visitor•Multi-methodsjjhou.928@gmail.com•Inheritance•Composition•Delegation•LSP•OCPjjhou.928@gmail.com(Cls*pobj){pobj-xxx();}voidfunc2(Clsobj){obj.xxx();}voidfunc3(Cls&obj){obj.xxx();}Clsobj;func1(&obj);func2(obj);func3(obj);voidfunc1(Cls*pobj){pobj-xxx();}voidfunc2(Clsobj){obj.xxx();}voidfunc3(Cls&obj){obj.xxx();}Clsobj;func1(&obj);func2(obj);func3(obj);reference通常不用於變數的修飾,主要用於參數和returntype的修飾。使用byreference時,既享受bypointer的好處又保持介面能夠與byvalue相同。呼叫端介面相同,很好。介面不同,困擾。被呼叫端寫法相同,很好。新建的objects乃配置於一塊被稱為heap的系統記憶體中。所有objects都經由objectreferences進行存取。任何看起來持有object的變數事實上內含的是一個referencetoobject(此處可稱之為址參器)。這種變數型別稱為reference型別,對比於基本型別(其變數儲存的是該型別的值)。Objectreferences如果不指向任何object,即為null。大部分時候你可以模糊對待「實際的objects」和「referencestoobjects」之間的區別。當你真正的意思是「傳遞一個objectreference給某函式」時,你可以說成「傳遞一個object給某函式」。只有在兩者的區別造成影響時我們才謹慎對待之。大部分時候你可以互換使用object和objectreference這兩個詞。Java有指標嗎?比較精確的說法是,Java有指標。是的,Java之中除了基本型別,每個object的識別名稱都是指標。但它們的作用是受限的,不僅受到編譯器的保護,也受執行期系統的保護。換句話說Java有指標但是沒有指標運算。這正是reference,可被想像為安全的指標。那麼,Java是passbyvalue抑或passbyreference呢?jjhou.928@gmail.com{public:complex(_FLTr=0,_FLTi=0):re(r),im(i){}complex&operator+=(constcomplex&);complex&operator-=(constcomplex&);complex&operator*=(constcomplex&);complex&operator/=(constcomplex&);_FLTreal()const{returnre;}_FLTimag()const{returnim;}private:_FLTre,im;};classcomplexfloat;classcomplexdouble;classcomplexlongdouble;templateclass_FLTclasscomplex{public:complex(_FLTr=0,_FLTi=0):re(r),im(i){}complex&operator+=(constcomplex&);complex&operator-=(constcomplex&);complex&operator*=(constcomplex&);complex&operator/=(constcomplex&);_FLTreal()const{returnre;}_FLTimag()const{returnim;}private:_FLTre,im;};classcomplexfloat;classcomplexdouble;classcomplexlongdouble;publicinterfaceIteratorE{booleanhasNext();Enext();voidremove();}publicinterfaceIteratorE{booleanhasNext();Enext();voidremove();}C++codeinC++StandardLibrary(GCC2.91)JavacodeinJDK1.5.0publicinterfaceIterator{booleanhasNext();Objectnext();voidremove();}publicinterfaceIterator{booleanhasNext();Objectnext();voidremove();}JavacodeinJDK1.4.2jjhou.928@gmail.com•所謂複合,是指classobject中有一些classmembers。例如:又名:containment,embedding,layering,has-a,combinationclassCMyDoc:publicCDocument{private:CObListmyList;};classCMyDoc:publicCDocument{private:CObListmyList;};•我們說objectA擁有(own,have)objectB,或說B是A的成因(isresponsiblefor),或說B是A的一部分(apartof)。A和B的生命期完全相同。BAnJava雖然邏輯上有composition,但實際上(從ObjectModel的角度)應該都屬於delegation,因為Javafields都是objectreference,並沒有stackobjectfields。jjhou.928@gmail.com在此技術下,兩個objects協同處理訊息請求(messagerequest)。訊息接收者(委託者)授權給「受託者」全權處理訊息。這和「subclass將訊息回應動作委託baseclass完成」的情況有一點兒類似。然而,在Inheritance情況下baseclass內的操作函式透過'this'ptr便能處理「訊息接收者」(subclass)本身。但在delegation情況下,委託者必須將自己以參數型式傳給「受託者」,後者才有機會接觸「委託者」本尊。delegation的主要優點是可以輕易地在執行時期組合各種行為,並改變組合方式。OnFileOpen()Serialize()CMyDocCMyDocmyDoc;myDoc.OnFileOpen(CDocument*this);CMyDocmyDoc;myDoc.OnFileOpen(CDocument*this);CDocumentm_frame-draw(this)繼承必須明白寫出不必明白寫出ShapeWindowdelegate1draw(Window*)draw()m_frame:Shape*委託者(delegator)受託者(delegatee)[ugUpQtvTXQn][ugUpQvQtf`][tgUpQuvTf](其內會呼叫this-Serialize())Serialize()jjhou.928@gmail.com(Open-ClosedPrinciple)開放封閉守則ref《AgileSoftwareDevelopment,Principles,Patterns,andPractices》所有系統在它的生命週期中都會改變。如何才能在面對變動的情況下創造出穩定且可長久延續的設計呢?BetrandMeyer在l988年創造了聞名當今的OCP。如果OCP應用得宜,未來的變更是以增添新程式碼達成,而不是修改運作正常的舊有程式碼。OCP具有兩個主要特性:•對擴充開放(Openforextension)。這表示模組的行為可擴充。也就是說我們可以改變模組所做的事。•對修改封閉(Closedformodification)。擴充模組行為並不會對模組源碼或二進制碼造成改變。模組的二進制可執行版本不論是linkablelibrary或DLL或Java.jar,都不會改動。擴充模組行為的典型方法是修改模組源碼,不能修改的模組通常被認為具有固定的行為。怎麼可能不修改模組源碼而還能改變模組行為呢?抽象化是關鍵所在。軟件實物(classes、modules、functions)對擴充應保持開放,對修改應維持封閉。jjhou.928@gmail.com(Open-ClosedPrinciple)開放封閉守則在任何OOPL中都可以創造出「固定並且代表一組無限可能的行為」的抽象概念。這些抽象概念就是abstractbaseclasses,而那組無限可能的行為則以所有可能的derivedclasses來表現。模組可以操作抽象概念。由於依存於固定之抽象概念,所以模組可對修改保持封閉,而又可透過創造抽象概念之newderivedclasses對模組的行為加以擴充。TemplateMethod和Strategy(Policy)是滿足OCP的最常見手法,它們都表達了一個清晰的分離(separation)概念,將通用功能性從該功能的實作細節中分離出來。遵循OCP的代價是昂貴的,需要花費開發期的時間和人力來創造適當的抽象概念。這些抽象概念也增添了軟件設計的複雜度,而開發人員能夠承擔的抽象概念數量有其極限。顯然我們希望把OCP的應用限制在有可能發生的變更上。怎樣知道哪些變更有可能發生呢?我們做適當的研究調查、提出適切的問題、運用經驗與常識。最後就等變更發生!在許多方面,O