最近在看設計模式。在學習初期一直有一個問題困擾着我,那就是UML類圖
中的各類結構用python代碼是如何實現的?這個在初期能夠說是深深的困擾着個人設計模式
學習之路。下面我將介紹一下我本身總結的實現,若是有錯誤也但願各位給指出,不勝感激。java
本文的UML圖採用Enterprise Architect繪製。
Python版本2.7.12
(在用了Enterprise Architect 後才知道他有從類圖導出代碼的功能,/捂臉
早知道就用這個學習各類結構的實現了。文末有介紹如何用Enterprise Architect 導出代碼。)python
類圖是由類和類之間的鏈接關係構成。
類咱們這裏只介紹類和抽象類。
鏈接關係咱們介紹泛化(generalization)、實現(realize)、聚合(aggregation)、組合(compositon)、關聯(assocation)和依賴(dependency)共六種。segmentfault
接口在UML中的圖形爲
設計模式
能夠看到再其上半部分有一個interface的表示。在接口中通常只給出接口的定義
而實現通常放在子類和實現。app
在python中本事是沒有接口和抽象類這一律唸的,可是能夠經過abc(Abstract Base Class)這個python庫來實現。或者是經過拋出NotImplementedError這個異常來實現。工具
from abc import ABCMeta, abstractmethod, abstractproperty class Drawable: __metaclass__ = ABCMeta @abstractproperty def size(self): pass @abstractmethod def draw(self, x, y, scale=1.0): pass class Cicle(Drawable): def size(self): print 'Cicle' def draw(self, x, y, scale=1.0): print str(x*y*scale) c = Cicle()
若是在子類裏面沒有實現方法,當實例化子類的時候會報錯。abc模塊的具體使用這裏就不介紹了。放上abc的 PEP3119學習
class Drawable1: def size(self): raise NotImplementedError def draw(self, x, y, scale=1.0): raise NotImplementedError class Cicle(Drawable): def size(self): print 'Cicle' def draw(self, x, y, scale=1.0): print str(x*y*scale) c = Cicle() c.draw()
這裏若是子類沒有實現方法,在實例化的時候不會報錯。只有當調用到未實現的方法時候纔會報錯。這種經過abc的註冊機制也能夠實現。ui
類的圖示以下
spa
能夠看到整個圖形分爲三部分:上面爲類名,中間爲類屬性,下面爲類方法。
其中能夠看到有- + 和# 三種符號,其分別表明私有、公有、保護。其中保護變量在python中是不存在的。
公有變量能夠在類外被直接訪問。且能夠被子類繼承,私有變量只能再此類中被訪問且不能夠被子類繼承。設計
class Flower(object): def __init__(self, floral=None, leaf=None): self.floral = floral self.__leaf = leaf def flowing(self): print 'flower' def __grow(self): print 'grow grow'
其中以兩條下劃線開頭的變量爲私有變量,方法爲私有方法。
其實在python中也不是在類外面沒法訪問到私有變量或方法。只是在生成python字節碼的時候在編譯器自動再含有__ 開頭的屬性或變量前加上了 _{classname}了你能夠在類外經過 _Flower__leaf 訪問到__leaf屬性,固然這並無什麼意義。
首先咱們來看一下泛化關係的UML結構圖。
鏈接器的是由一條直線和一個三角組成的,鏈接的兩端都是類。在代碼中的結構就是繼承非抽象類。
class Car(object): def __init__(self): self.wheel = ['11', '12', '21', '22'] self.body = 'car body' def run(self): print self.wheel print self.body def horn(self): print 'bbbbbbb' class SUV(Car): def run(self): print 'suv' super(SUV, self).run() class Jeep(Car): def run(self): print 'jeep' super(Jeep, self).run() jeep = Jeep() jeep.run() jeep.horn()
咱們能夠看到Jeep和SUV繼承了Car這個非抽象類
從圖中能夠看出實現關係爲一個三角箭頭加一段虛線構成。箭頭指向抽象類。
在代碼中表現爲繼承抽象類。
class Vehicle(object): def run(self): raise NotImplementedError class Car(Vehicle): def run(self): print 'car run run' class Bicycle(Vehicle): def run(self): print 'bicycle run run'
代碼中Car和Bicycle繼承了Vehicle這個抽象類。
關聯關係是用一條直線表示的;它描述不一樣類的對象之間的結構關係;它是一種靜態關係, 一般與運行狀態無關,通常由常識等因素決定的;它通常用來定義對象之間靜態的、自然的結構; 因此,關聯關係是一種「強關聯」的關係;
好比,乘車人和車票之間就是一種關聯關係;學生和學校就是一種關聯關係;[1]
關聯關係爲一條直線,能夠有箭頭,如圖表示car知道Moter的存在而Moter不知道Car的存在。表如今代碼中就是Car中有一個屬性爲Motor類的實例。也能夠爲雙箭頭表示互相知道。
class Motor(object): pass class Car(object): def __init__(self): self.motor = Motor()
他描述一個對象在運行期間會用到另外一個對象的關係.與關聯關係不一樣的是,它是一種臨時性的關係,一般在運行期間產生,而且隨着運行時的變化; 依賴關係也可能發生變化;
顯然,依賴也有方向,雙向依賴是一種很是糟糕的結構,咱們老是應該保持單向依賴,杜絕雙向依賴的產生;
注:在最終代碼中,依賴關係體現爲類構造方法及類方法的傳入參數,箭頭的指向爲調用關係;依賴關係除了臨時知道對方外,仍是「使用」對方的方法和屬性;[1]
從圖中能夠看出依賴關係爲在類的方法中將另外一個類看成參數傳入。
class People(object): def cooking(self, wok): wok.cook() class Wok(object): def cook(self): print 'cook'
咱們在People的cooking方法中傳入了Wok實例,調用其cook方法,完成people的cooking動做。
組合關係表示總體由部分構成,可是當總體不存在時部分也不存在,是一種強依賴關係。
從圖中看到組合關係是由一個實心的菱形箭頭表示,菱形箭頭指向總體。 公司由部分組成。當公司不存在了,部門也就不存在了。
class Company(object): def __init__(self): self.__departments = [] def build_department(self, department): self.__departments.append(department) class Department(object): def __init__(self, name): self.name = name c = Company() d1 = Department('1') d2 = Department('2') c.build_department(d1) c.build_department(d2)
聚合關係表示總體由部分構成可是當總體不存在的時候部分也是能夠存在的。
從圖中看到聚合關係由一個空心的菱形箭頭表示, 菱形箭頭指向總體。及公司是由人組成的。 當公司不存在的時候人仍是能夠單獨存在的。 組合關係和聚合關係由常識來區別的。在實現上區別不大。
class Company(object): def __init__(self): self.__employees = [] def add_employee(self, people): self.__employees.append(people) class People(object): pass c = Company() p1 = People() p2 = People() p3 = People() c.add_employee(p1) c.add_employee(p2) c.add_employee(p3)
有點長我把這個再寫一篇,
如何從Enterprise Architect 導出代碼