- 人人都懂設計模式:從生活中領悟設計模式(Python實現)
- 羅偉富
- 2832字
- 2019-06-19 15:57:00
基礎篇
Everybody Knows Design Patterns
第0章 啟程之前,請不要錯過我
0.1 Python精簡入門
設計模式與編程語言沒有關系,它是對面向對象思想的靈活應用和高度概括,你可以用任何一種語言來實現它,但還是需要用一種語言來舉例。除特別說明外,本書的所有示例源碼,均采用 Python 實現。如果你初次接觸 Python,請務必先閱讀本章的內容;如果你已經很熟悉Python,可直接跳過本章的內容。
0.1.1 Python的特點
Python崇尚優美、清晰、簡單,是一種優秀并被廣泛使用的語言。
與Java和C++這些語言相比,Python最大的幾個特點是:
(1)語句結束不用分號“;”。
(2)代碼塊用縮進來控制,而不用大括號“{}”。
(3)變量使用前不用事先聲明。
從其他語言剛轉到Python的時候可能會有點不適應,用一段時間就好了!
個人覺得,在所有的高級計算機語言中,Python是最接近人類的自然語言的。Python的語法、風格都與英文的書寫習慣非常接近,Python 的這種風格被稱為 Pythonic。如條件表達式,在Java和C++語言中是這樣的:

而在Python語言中是這樣的:

有沒有覺得第二種方式更接近人類的自然思維?
0.1.2 基本語法
1.數據類型
Python是一種動態語言,定義變量時不需要在前面加類型說明,而且不同類型之間可以方便地相互轉換。Python有五個標準的數據類型:
(1)Numbers(數字)
(2)String(字符串)
(3)List(列表)
(4)Tuple(元組)
(5)Dictionary(字典)
其中 List、Tuple、Dictionary 為容器,將在下一部分介紹。Python 支持四種不同的數字類型:int(有符號整型)、float(浮點型)、complex(復數)(說明:Python 3中已去除long類型,與int類型合并)。
每個變量在使用前都必須賦值,變量賦值以后才會被創建。
源碼示例0-1

輸出結果:


2.常用容器
1)List
List(列表)是Python中使用最頻繁的數據類型,用“[]”標識。列表可以完成大多數集合類的數據結構實現,類似于Java中的ArrayList和C++中的Vector。此外,一個List中還可以同時包含不同類型的數據,支持字符、數字、字符串,甚至可以包含列表(即嵌套)。
(1)列表中值的切割也可以用到變量[頭下標:尾下標],這樣就可以截取相應的列表,從左到右索引默認從0開始,從右到左索引默認從-1開始,下標可以為空(表示取到頭或尾)。
(2)加號(+)是列表連接運算符,星號(*)是重復操作。
源碼示例0-2

輸出結果:


2)Tuple
Tuple(元組)是另一種數據類型,用“()”標識,內部元素用逗號隔開。元組不能二次賦值,相當于只讀列表,用法與List類似。Tuple相當于Java中的final數組和C++中的const數組。
源碼示例0-3

輸出結果:

3)Dictionary
Dictionary(字典)是Python中除列表以外最靈活的內置數據結構類型。字典用“{ }”標識,由索引(key)和它對應的值value組成。相當于Java和C++中的Map。
列表是有序的對象集合,字典是無序的對象集合。兩者之間的區別在于:字典中的元素通過鍵存取,而不通過偏移存取。
源碼示例0-4


結果:

3.類的定義
使用class語句來創建一個新類,class之后為類的名稱并以冒號結尾,實例如下:

類的幫助信息可以通過 ClassName._doc_查看,類體(class_suite)由類成員、方法、數據屬性組成,舉例如下。
源碼示例0-5

其中_init_為初始化函數,相當于構造函數。
1)訪問權限
● _foo_:定義的是特殊方法,一般是系統定義名字,類似_init_()。
● _foo:以單下畫線開頭時表示的是 protected 類型的變量,即保護類型只允許其本身與子類進行訪問,不能用于 from module import *。
● __foo:以雙下畫線開頭時,表示的是私有類型(private)的變量,即只允許這個類本身進行訪問。
2)類的繼承
類的繼承語法結構如下:

Python中繼承中的一些特點:
(1)在繼承中基類的初始化方法_init_()不會被自動調用,它需要在其派生類的構造中親自專門調用。
(2)在調用基類的方法時,需要使用super()前綴。
(3)Python總是首先查找對應類型的方法,不能在派生類中找到對應的方法時,它才開始到基類中逐個查找(先在本類中查找調用的方法,找不到才去基類中找)。
如果在繼承元組中列了一個以上的類,那么它就被稱作“多重繼承”。
3)基礎重載方法
Python的類中有很多內置的基礎重載方法,我們可以通過重寫這些方法來實現一些特殊的功能。這些方法如表0-1所示。
表0-1 基礎重載方法

0.1.3 一個例子讓你頓悟
我們將一段 Java 代碼對應到 Python 中來實現,進行對比閱讀,相信你很快就能明白其中的用法。
源碼示例0-6 Java代碼


源碼示例0-7 對應的Python代碼



源碼示例0-6和源碼示例0-7的結果是一樣的,如下:

0.1.4 重要說明
(1)為了降低程序復雜度,本書用到的所有示例代碼均不考慮多線程安全,望借鑒源碼的讀者注意。
(2)本書所有源碼均在Python 3.6.3下編寫,Python 3.0以上都可以正常運行。
(3)源碼地址:https://github.com/luoweifu/PyDesignPattern,本書所有源代碼可在此免費閱讀和下載。
0.2 UML精簡概述
0.2.1 UML的定義
UML是英文 Unified Modeling Language 的縮寫,簡稱UML(統一建模語言),它是一種由一整套圖組成的標準化建模語言,用于幫助系統開發人員闡明、設計和構建軟件系統。
UML 的這一整套圖被分為兩組,一組叫結構性圖,包含類圖、組件圖、部署圖、對象圖、包圖、組合結構圖、輪廓圖;一組叫行為性圖,包含用例圖、活動圖(也叫流程圖)、狀態機圖、序列圖、通信圖、交互圖、時序圖。其中類圖是應用最廣泛的一種圖,經常被用于軟件架構設計中。
0.2.2 常見的關系
類圖用于表示不同的實體(人、事物和數據),以及它們彼此之間的關系。該圖描述了系統中對象的類型以及它們之間存在的各種靜態關系,是一切面向對象方法的核心建模工具。
UML 類圖中最常見的幾種關系有:泛化(Generalization)、實現(Realization)、組合(Composition)、聚合(Aggregation)、關聯(Association)和依賴(Dependency)。這些關系的強弱順序為:泛化=實現 > 組合 > 聚合 > 關聯 > 依賴。
1.泛化
泛化(Generalization)是一種繼承關系,表示一般與特殊的關系,它指定了子類如何特化父類的所有特征和行為。
如:哺乳動物具有恒溫、胎生、哺乳等生理特征,貓和牛都是哺乳動物,也都具有這些特征,但除此之外,貓會捉老鼠,牛會耕地,如圖0-1所示。

圖0-1 泛化
2.實現
實現(Realization)是一種類與接口的關系,表示類是接口所有特征和行為的實現。
如:蝙蝠也是哺乳動物,它除具有哺乳動物的一般特征之外,還會飛,我們可以定義一個IFlyable的接口,表示飛行的動作,而蝙蝠需要實現這個接口,如圖0-2所示。

圖0-2 實現
3.組合
組合(Composition)也表示整體與部分的關系,但部分離開整體后無法單獨存在。因此,組合與聚合相比是一種更強的關系。
如:我們的電腦由CPU、主板、硬盤、內存組成,電腦與CPU、主板、硬盤、內存是整體與部分的關系,但如果讓CPU、主板等組件單獨存在,就無法工作,因此沒有意義,如圖0-3所示。

圖0-3 組合
4.聚合
聚合(Aggregation)是整體與部分的關系,部分可以離開整體而單獨存在。
如:一個公司會有多個員工,但員工可以離開公司單獨存在,離職了依然可以好好地活著,如圖0-4所示。

圖0-4 聚合
5.關聯
關聯(Association)是一種擁有關系,它使一個類知道另一個類的屬性和方法。關聯可以是雙向的,也可以是單向的。
如:一本書會有多個讀者,一個讀者也可能會有多本書,書和讀者是一種雙向的關系(也就是多對多的關系);但一本書通常只會有一個作者,是一種單向的關系(就是一對一的關系,也可能是一對多的關系,因為一個作者可能會寫多本書),如圖0-5所示。

圖0-5 關聯
6.依賴
依賴(Dependency)是一種使用的關系,即一個類的實現需要另一個類的協助,所以盡量不要使用雙向的互相依賴。
如:所有的動物都要吃東西才能活著,動物與食物就是一種依賴關系,動物依賴食物而生存,如圖0-6所示。

圖0-6 依賴