【转】第00课导读:生活中的设计模式——启程之前,请不要错过我
-
-
- 為什么叫設計模式
- 什么是設計模式
- 設計模式與生活有什么聯系
- 為什么要學設計模式
- 如何進行學習
- 為什么選擇 Python
- 彌補市場空缺
- 大勢所趨,Python 已然成風
- 簡單的 Python 基礎
- Python 的特點
- 基本語法
- 常用容器
- List(列表)
- Tuple(元組)
- Dictionary(字典)
- 類的定義
- Demo 讓你頓悟
- 重要說明
- 為什么叫設計模式
-
兩年前 CSDN 出了一個產品叫 ink,旨在提供一個高質量的寫作環境,那時就有寫設計模式這一系列的想法了,而且也確實寫了,在 ink 里寫了三篇文章,后來不知道什么原因這個產品下架了,寫的三篇文章也沒了,這事也就一直被擱置了;直到今天,我想重新開始,以全新的方式和思路重新寫這一系列內容!
- 文章的特點:?從生活的小故事開始,由淺入深,逐步闡述設計模式的思想,并抽象出代碼模型(骨架)。
- 追求的境界:?用最通俗的語言闡述最難懂的概念;用最簡單的語法實現最復雜的邏輯;用最短小的代碼寫出最強悍的程序!
為什么叫設計模式
什么是設計模式
設計模式最初是被 GoF 于 1995 年提出的,GoF(Gang of Four,四人幫)即 Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides。他們四人于 1995 年出版了一本書《Design Patterns:Elements of Reusable Object-Oriented Software》(翻譯成中文是《設計模式 可復用面向對象軟件的基礎》),第一次將設計模式提升到理論高度,并將之規范化,該書提出了 23 種經典的設計模式。
設計模式(Design Pattern)是一套被反復使用、多數人知曉的、無數工程師實踐的代碼設計經驗的總結,它是面向對象思想的高度提煉和模板化,使用設計模式是為了讓代碼具有更高的可重用性,更好的靈活性和可拓展性,更易被人閱讀和理解。GoF 提到的模式有四個基本要素:
- 模式名稱:助記名,方便討論、交流、傳播;
- 問題:該模式是用來解決哪類實際問題,即它的應用場景;
- 解決方案:設計的組成部分,它們之間的相互關系及各自的職責和協作方式;
- 效果:使用模式能達到的效果,即對使用條件的權衡取舍。
設計模式與生活有什么聯系
我一直堅信:程序源于生活,又高于生活!程序的靈魂在于思維的方式,而思維的靈感來源于生活的精彩。互聯網是一個虛擬的世界,而程序本身就是對生活場景的虛擬和抽象,每一個模式我都能在生活中找到他的影子。比如,說到狀態模式我能想到水有冰、水、氣三種狀態,而人也有少、壯、老三個不同的階段;提起中介模式我能立馬想到房產中介;看到單例模式,腦海中會即刻浮現心目中的那個她……
設計模式是面向對象的高度抽象和總結,而越是抽象的東西,越難以理解。本系列文章的目地就是為了降低設計模式的閱讀門檻,以生活中的小故事開始,用風趣的方式,由淺入深地講述每一個模式。讓你再次看到設計模式時不只是一個模式,還是生活中的一個個小確幸!程序不是冷冰冰的代碼,它還有生活的樂趣和特殊意義。
為什么要學設計模式
設計模式是軟件開發人員在軟件開發過程中面臨的一般問題的解決方案,這些解決方案是眾多軟件開發人員經過相當長的一段時間的試驗和總結的成果。所以不管你是新手還是老手,學習設計模式都將為你的代碼設計帶來莫大的幫助。
學習設計模式的理由有很多,這里只列出幾個最現實的:
- 擺脫面試的窘境,不管是前端工程師還是后端工程師,亦或是全棧工程師,設計模式是面試時必問的一道題。
- 讓程序設計能力有一個質的提升,不再是寫一堆結構復雜、難以維護的爛代碼。
- 對面向對象的思想有一個更高層次的理解。
如何進行學習
1.熟悉一門面向對象語言
首先,要熟悉至少一門面向對象的計算機語言。如果沒有,請根據自己的學習愛好,或希望從事的工作,先選擇一門面向對象語言(C#、Java、Python、Go 等都可以)進行學習和實戰,對抽象、繼承、多態、封裝有一定的基礎之后,再來看本系列的文章內容。
2.了解 Python 的基本語法
對 Python 的基本語法有一個簡單了解。Python 語法非常簡單,只要有一定的編程語言基礎,通過下文的介紹很快就能理解的。
3.學會閱讀 UML 圖
UML(Unified Modeling Language)稱為統一建模語言或標準建模語言,是面向對象軟件的標準化建模語言。UML 規范用來描述建模的概念有:類(對象的)、對象、關聯、職責、行為、接口、用例、包、順序、協作以及狀態。
UML 類圖表示不同的實體(人、事物和數據)如何彼此相關;換句話說,它顯示了系統的靜態結構。想進一步了解類圖中的各種關系,可參考以下文章:
- UML 類圖關系大全
- UML 類圖關系(泛化 、繼承、實現、依賴、關聯、聚合、組合)
4.閱讀本系列文章
通過閱讀本系列文章,以輕松愉快的方式學習設計模式和編程思想。本系列文章沒有閱讀的先后順序,每一章都是單獨成文,可從任意一篇文章開始。
為什么選擇 Python
雖然說設計模式與編程語言沒有關系,它是對面向對象思想的靈活應用和高度概括,可以用任何一種語言來實現它,但總歸是需要用一種語言進行舉例的。本系列文章的所有示例代碼均使用 Python 語言編寫,為什么選擇 Python,主要是基于以下兩個原因。
彌補市場空缺
設計模式于 1995 被 GoF 提出,被廣泛應用于熱門的面對象語言。目前用 Java、C# 描述的設計模式的書籍和資料已經非常多了,但用 Python 來描述的真是太少了;我在當當上搜索了一下“Python 設計模式”關鍵字,發現只有那零星的幾本書。而作為已經擠進 Top4 的 Python 語言,這明顯是不夠的。同時,Python 已經越來越成熟,也越來越多地被使用,作為一個有技術追求的 IT人有必要了解一下基于 Python 代碼設計。
大勢所趨,Python 已然成風
- C 語言誕生于 1972 年,確隨著 Unix 的誕生才深深植根于各大操作系統;
- C++ 語言誕生于 1983 年,確因微軟的可視化桌面操作系統才得以廣泛傳播;
- Java 語言誕生于 1995 年,確因互聯網的迅速崛起才變得家喻戶曉;
- Python 語言誕生于 1991 年,而下一場技術革命已然開始,AI 時代已然成風。在 AI 領域中已經被廣泛使用的 Python 語言必將成為下一個時代的第一開發語言!
最熱門的 AI 開源框架 PyTorch 和 TensorFlow 都已經采用了 Python 作為接口和開發語言。除此之外,還有一堆的 AI 相關的框架庫,也都紛紛采用,如 AIMA、pyDatalog、SimpleAI、PyBrain、PyML 等。
作為這么一門有前途的語言,必然是要去學習和使用的。
簡單的 Python 基礎
如果已經熟悉 Python 語言,這一部分的內容可直接跳過!
Python 的特點
Python 崇尚優美、清晰、簡單,是一個優秀并廣泛使用的語言。
與 Java 和 C++ 這些語言相比,Python 最大的兩個特點是:
- 語句結束不用分號“;”。
- 代碼塊用縮進來控制,而不用大括號“{}”。
剛轉過來的時候可能會有點不適,用一段時間就好了!
個人覺得,在所有的高級計算機語言中,Python 是最接近人類自然語言的。Python 的語法、風格都與英文的書寫習慣非常接近,Python 的這種風格被稱為 Pythonic,如條件表達式,在 Java 和 C++ 中是這樣的:
int min = x < y ? x : y而 Python 是這樣的:
min = x if x < y else y有沒有覺得第二種方式更接近人類的自然思維?
基本語法
數據類型
Python 是一種弱類型的語言,變量的定義不需要在前面加類型說明,而且不同類型之間可以方便地相互轉換。Python 有五個標準的數據類型:
- Numbers(數字)
- String(字符串)
- List(列表)
- Tuple(元組)
- Dictionary(字典)
其中 List、Tuple、Dictionary 為容器,將在下一部分介紹。Python 支持四種不同的數字類型:int(有符號整型)、long(長整型)、float(浮點型)、complex(復數)。
每個變量在使用前都必須賦值,變量賦值以后該變量才會被創建。
Demo:
?age = 18 # int
weight = 62.51 # float
name = "Tony" # string
print("age:", age)
print("weight:", weight)
print("name:", name)
# 變量的類型可以直接改變
age = name
print("age:", age)
a = b = c = 5
# a,b,c三個變量指向相同的內存空間,具有相同的值
print("a:", a, "b:", b, "c:", c)
print("id(a):", id(a), "id(b):", id(b), "id(c):", id(c))
結果:
?age: 18
weight: 62.51
name: Tony
age: Tony
a: 5 b: 5 c: 5
id(a): 1457772400 id(b): 1457772400 id(c): 1457772400
常用容器
List(列表)
List(列表)是 Python 中使用最頻繁的數據類型,用 [ ] 標識。
列表可以完成大多數集合類的數據結構實現。類似于 Java 中的 ArrayList,C++ 中的 Vector。此外,一個 List 中還可以同時包含不同類型的數據,支持字符、數字、字符串,甚至可以包含列表(即嵌套)。
- 列表中值的切割也可以用到變量 [頭下標:尾下標] ,就可以截取相應的列表,從左到右索引默認 0 開始,從右到左索引默認 -1 開始,下標可以為空表示取到頭或尾。
- 加號(+)是列表連接運算符,星號(*)是重復操作。
Demo:
?list = ['Thomson', 78, 12.58, 'Sunny', 180.2]
tinylist = [123, 'Tony']
print(list) # 輸出完整列表
print(list[0]) # 輸出列表的第一個元素
print(list[1:3]) # 輸出第二個至第三個元素
print(list[2:]) # 輸出從第三個開始至列表末尾的所有元素
print(tinylist * 2) # 輸出列表兩次
print(list + tinylist) # 打印組合的列表
list[1] = 100 # 修改第二個元素的值
print(list) # 輸出完整列表
list.append("added data")
print(list) # 輸出增加后的列表
結果:
?['Thomson', 78, 12.58, 'Sunny', 180.2]
Thomson
[78, 12.58]
[12.58, 'Sunny', 180.2]
[123, 'Tony', 123, 'Tony']
['Thomson', 78, 12.58, 'Sunny', 180.2, 123, 'Tony']
['Thomson', 100, 12.58, 'Sunny', 180.2]
['Thomson', 100, 12.58, 'Sunny', 180.2, 'added data']
Tuple(元組)
Tuple(元組)是另一個數據類型,元組用“()”標識,內部元素用逗號隔開。元組不能二次賦值,相當于只讀列表,用法與 List 類似。Tuple 相當于 Java 中的 final 數組,C++ 中的 const 數組。
Demo:
?tuple = ('Thomson', 78, 12.58, 'Sunny', 180.2)
tinytuple = (123, 'Tony')
print(tuple) # 輸出完整元組
print(tuple[0]) # 輸出元組的第一個元素
print(tuple[1:3]) # 輸出第二個至第三個的元素
print(tuple[2:]) # 輸出從第三個開始至列表末尾的所有元素
print(tinytuple * 2) # 輸出元組兩次
print(tuple + tinytuple)# 打印組合的元組
# tuple[1] = 100 # 不能修改元組內的元素
結果:
?('Thomson', 78, 12.58, 'Sunny', 180.2)
Thomson
(78, 12.58)
(12.58, 'Sunny', 180.2)
(123, 'Tony', 123, 'Tony')
('Thomson', 78, 12.58, 'Sunny', 180.2, 123, 'Tony')
Dictionary(字典)
Dictionary(字典)是 Python 中除列表以外最靈活的內置數據結構類型。字典用“{ }”標識,字典由索引(key)和它對應的值 value 組成,相當于 Java 和 C++ 中的 Map。
列表是有序的對象集合,字典是無序的對象集合。兩者之間的區別在于:字典當中的元素是通過鍵來存取的,而不是通過偏移存取。
Demo:
?dict = {}
dict['one'] = "This is one"
dict[2] = "This is two"
tinydict = {'name': 'Tony', 'age': 24, 'height': 177}
print(dict['one']) # 輸出鍵為'one' 的值
print(dict[2]) # 輸出鍵為 2 的值
print(tinydict) # 輸出完整的字典
print(tinydict.keys()) # 輸出所有鍵
print(tinydict.values())# 輸出所有值
結果:
?This is one
This is two
{'name': 'Tony', 'age': 24, 'height': 177}
dict_keys(['name', 'age', 'height'])
dict_values(['Tony', 24, 177])
類的定義
使用 class 語句來創建一個新類,class 之后為類的名稱并以冒號結尾,如下實例:
?class ClassName:
'類的幫助信息' #類文檔字符串
class_suite #類體
類的幫助信息可以通過 ClassName.__doc__?查看,class_suite 由類成員,方法,數據屬性組成。如:
?class Test:
"這是一個測試類"
def __init__(self):
self.__ivalue = 5
def getvalue(self):
return self.__ivalue
其中,__init__?為初始化函數,相當于構造函數。
訪問權限:
- __foo__:定義的是特殊方法,一般是系統定義名字,類似?__init__() 之類的。
- _foo:以單下劃線開頭的表示的是 protected 類型的變量,即保護類型只能允許其本身與子類進行訪問,不能用于 from module import *。
- __foo:雙下劃線的表示的是私有類型(private)的變量,只能是允許這個類本身進行訪問了。
類的繼承:
繼承的語法結構如下:
?class 派生類名(基類名):
類體
Python 中繼承中的一些特點:
- 在繼承中基類的構造(__init__()?方法)不會被自動調用,它需要在其派生類的構造中親自專門調用。
- 在調用基類的方法時,需要使用 super() 前綴。
- Python 總是首先查找對應類型的方法,如果它不能在派生類中找到對應的方法,它才開始到基類中逐個查找(先在本類中查找調用的方法,找不到才去基類中找)。
如果在繼承元組中列了一個以上的類,那么它就被稱作“多重繼承”。
基礎重載方法
Python 的類中有很多內置的方法,我們可以通過重寫這些方法來實現一些特殊的功能,這些方法有:
| 1 | __init__(self [,args…] ) | 構造函數 | obj = className(args) |
| 2 | __del__(self) | 析構方法, 刪除一個對象 | del obj |
| 3 | __repr__(self) | 轉化為供解釋器讀取的形式 | repr(obj) |
| 4 | __str__(self) | 用于將值轉化為適于人閱讀的形式 | str(obj) |
| 5 | __cmp__(self, x) | 對象比較 | cmp(obj, x) |
Demo 讓你頓悟
我們將一段 Java 的代碼對應到 Python 中來實現,進行對比閱讀,相信很快就能明白其中的用法。Java 代碼如下:
?class Person {
public static int visited;
Person(String name, int age, float height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void showInfo() {
System.out.println("name:" + name);
System.out.println("age:" + age);
System.out.println("height:" + height);
System.out.println("visited:" + visited);
Person.visited ++;
}
private String name;
protected int age;
public float height;
}
class Teacher extends Person {
Teacher(String name, int age, float height) {
super(name, age, height);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void showInfo() {
System.out.println("title:" + title);
super.showInfo();
}
private String title;
}
public class Test {
public static void main(String args[]) {
Person tony = new Person("Tony", 25, 1.77f);
tony.showInfo();
System.out.println();
Teacher jenny = new Teacher("Jenny", 34, 1.68f);
jenny.setTitle("教授");
jenny.showInfo();
}
}
對應的 Python 代碼:
?class Person:
"人"
visited = 0
def __init__(self, name, age, height):
self.__name = name
self._age = age
self.height = height
def getName(self):
return self.__name
def getAge(self):
return self._age
def showInfo(self):
print("name:", self.__name)
print("age:", self._age)
print("height:", self.height)
print("visited:", self.visited)
Person.visited = Person.visited +1
class Teacher(Person):
"老師"
def __init__(self, name, age, height):
super().__init__(name, age, height)
self.__title = None
def getTitle(self):
return self.__title
def setTitle(self, title):
self.__title = title
def showInfo(self):
print("title:", self.__title)
super().showInfo()
def testPerson():
"測試方法"
tony = Person("Tony", 25, 1.77)
tony.showInfo()
print();
jenny = Teacher("Jenny", 34, 1.68);
jenny.setTitle("教授");
jenny.showInfo();
testPerson()
自己測試一下,會發現結果是一樣的:
?name: Tony
age: 25
height: 1.77
visited: 0
title: 教授
name: Jenny
age: 34
height: 1.68
visited: 1
重要說明
- 為了降低程序復雜度,本系列文章中用到的所有示例代碼均不考慮多線程安全,望借鑒 Demo 的讀者注意。
- 本系列所有 Demo 均是在 Python 3.6.3 下編寫的,Python 3.0 以上應該都可以正常運行。
總結
以上是生活随笔為你收集整理的【转】第00课导读:生活中的设计模式——启程之前,请不要错过我的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# Azure 存储-Blob
- 下一篇: 李书福喜提魅族手机 吉利车机等来救星