(一)python 設計模式 --- 六大原則
單一職責原則(SRP:Single responsibility principle),一個類或者模組應該有且只有一個改變的原因,例如,搓衣板,既可以用來跪,也可以用來洗衣服。而在單一職責原理下,搓衣板的兩個功能就是引起這個類變化的兩個原因,就應該寫成兩個類
# -*- coding: utf-8 -*-
"""
單一職責原則
"""
class Person(object):
""" 人類 """
def duty(self, one):
""" Coder 的職責是寫程式碼 ,農民就負責鬥地主,其餘的學習 """
return one is "Coder" and "Coding" or one is "Farmer" and "Chinese poker" or "Studying"
if __name__ == '__main__':
p = Person()
print(p.duty("Coder"))
- 此時如果細分責任到每一個人,豈不是一堆的判斷,肯定不科學,所以儘量讓一個類或者一個模組做一件事
# -*- coding: utf-8 -*-
"""
單一職責原則
"""
class Person(object):
""" 人類 """
def duty(self, one):
""" Coder 的職責是寫程式碼 ,農民就負責鬥地主,其餘的學習 """
return one is "Coder" and "Coding" or one is "Farmer" and "Chinese poker" or "Studying"
class Coder(Person):
""" 農民 """
def duty(self):
""" Coder 的職責是寫程式碼 """
return "Coding"
class Farmer(Person) :
""" 程式設計師 """
def duty(self):
""" 農民就負責鬥地主 """
return "Chinese poker"
if __name__ == '__main__':
c = Coder()
print(c.duty())
f = Farmer()
print(f.duty())
里氏替換原則( LSP:Liskov Substitution Principle):任何基類可以出現的地方,子類一定可以出現。 LSP是繼承複用的基石,只有當衍生類可以替換掉基類,軟體單位的功能不受到影響時,基類才能真正被複用,而衍生類也能夠在基類的基礎上增加新的行為
子類必須完全實現父類的抽象方法,但不能覆蓋父類的非抽象方法
子類可以實現自己特有的方法
當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入引數更寬鬆。
當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。
子類的例項可以替代任何父類的例項,但反之不成立
# -*- coding: utf-8 -*-
import abc
import time
"""
里氏替換原則
"""
HOUR = 3600
class Person(object):
""" 人類 """
@abc.abstractmethod
def duty(self):
""" 職責 """
pass
class Coder(Person):
""" 程式設計師 """
def duty(self):
""" Coder 的職責是寫程式碼 """
return "Coding"
def sleep(self):
""" 有時睡5小時 """
time.sleep(5*HOUR)
class Farmer(Person):
""" 程式設計師 """
def duty(self):
""" 農民就負責鬥地主 """
return "Chinese poker"
def sleep(self):
""" 農民可以睡八小時 """
time.sleep(8*HOUR)
依賴倒置原則(Dependence Inversion Principle):高層模組不應該依賴低層模組,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象
# -*- coding: utf-8 -*-
import abc
import time
"""
里氏替換原則
"""
HOUR = 3600
class Person(object):
""" 人類 """
@abc.abstractmethod
def duty(self):
""" 職責 """
pass
class Coder(Person):
""" 程式設計師 """
def duty(self):
""" Coder 的職責是寫程式碼 """
return "Coding"
def sleep(self):
""" 睡5小時 """
time.sleep(5*HOUR)
介面隔離原則(Interface Segregation Principle) 這個原則的意思是:每個介面中不存在子類用不到卻必須實現的方法,如果不然就要將介面拆分,使用多個隔離的介面,比使用單個介面(多個介面方法集合到一個介面)要好
# -*- coding: utf-8 -*-
"""
介面隔離原則
"""
import abc
import time
import types
HOUR = 3600
class Person(object):
""" 人類 """
@abc.abstractmethod
def duty(self):
""" 職責 """
pass
class Coder(Person):
""" 程式設計師 """
def duty(self):
""" Coder 的職責是寫程式碼 """
return "Coding"
def sleep(self):
""" 有時睡5小時 """
time.sleep(5*HOUR)
# 方法一
# def programme(self, language='Php'):
# """ 例項動態方法 """
# return language
# 方法二
# @classmethod
# def programme(cls, language='Php'):
# """ 類動態方法 """
# return language
# 方法三
@staticmethod
def programme(language='Php'):
""" 靜態方法 """
return language
if __name__ == '__main__':
# 方法一:給例項繫結方法
# p = Coder()
# p.programme = types.MethodType(programme, p)
# print(p.programme('Python'))
# 方法二:
# p = Coder()
# Coder.programme = programme
# print(Coder.programme('Java'))
# print(p.duty())
# 方法三:靜態方法
p = Coder()
Coder.programme = programme
print(Coder.programme('Java'))
print(p.programme('Golang'))
print(p.duty())
迪米特原則: 一個物件應該對其他物件保持最少的瞭解。
問題由來:類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。
解決方案:儘量降低類與類之間的耦合。
軟體程式設計的總的原則:低耦合,高內聚。無論是面向過程程式設計還是面向物件程式設計,只有使各個模組之間的耦合儘量的低,才能提高程式碼的複用率。低耦合的優點不言而喻,要做到低耦合,正是迪米特法則要去完成的。
迪米特法則又叫最少知道原則,最早是在1987年由美國Northeastern University的Ian Holland提出。通俗的來講,就是一個類對自己依賴的類知道的越少越好。也就是說,對於被依賴的類來說,無論邏輯多麼複雜,都儘量地的將邏輯封裝在類的內部,對外除了提供的公共方法,不對外洩漏任何資訊。迪米特法則還有一個更簡單的定義:只與直接的朋友通訊。首先來解釋一下什麼是直接的朋友:每個物件都會與其他物件有耦合關係,只要兩個物件之間有耦合關係,我們就說這兩個物件之間是朋友關係。耦合的方式很多,依賴、關聯、組合、聚合等。其中,我們稱出現成員變數、方法引數、方法返回值中的類為直接的朋友,而出現在區域性變數中的類則不是直接的朋友。也就是說,陌生的類最好不要作為區域性變數的形式出現在類的內部。
開閉原則:一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉
- 不要改你以前寫的程式碼,你應該加一些程式碼去擴充套件原來的功能,來實現新的需求。好處很好理解,改原來的程式碼很容易影響原來的功能,特別是接手別人的程式碼,不理解原先業務場景的情況下。