物件導向設計原則
開放封閉原則:
一個軟體實體如類、模組和函式應該對擴充開放,對修改關閉。即軟體實體應儘量在不修改原有程式碼的情況下進行擴充套件。
里氏替換原則:
所有引用的父類的地方必須能透明的使用其子類的物件
依賴倒置原則:
高層模組不應該依賴低層模組,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象;即針對介面程式設計,而不是針對實現程式設計
工廠方法模式
定義:建立物件的介面(工廠介面),讓子類決定例項化哪一個產品類
角色:
抽象工廠角色(creator)
具體工廠角色(concrete creator)
抽象產品角色(product)
具體產品角色(concrete product)
例子:比如我們有一個染色的機器,我們要給指定的機器生產對應的工藝程式設計
from abc import ABCMeta, abstractmethod #抽象產品 class CraftProgramming(metaclass=ABCMeta): #abstract class @abstractmethod def setStep(self,step: list): pass #具體產品 class ModelTypeACraft(CraftProgramming): def __init__(self,childModelType=False): self.childModelType =childModelType def setStep(self,step: list): if self.childModelType: print(f"A機型-{self.childModelType}工藝工步為{step}") else: print(f"A機型工藝工步為{step}") class ModelTypeBCraft(CraftProgramming): def setStep(self,step: list): print(f"B機型工藝工步為{step}") #抽象工廠 class CraftProgrammingFactory(metaclass=ABCMeta): @abstractmethod def creatCraft(self): pass #具體工廠 class ModelTypeACraftFactory(CraftProgrammingFactory): def creatCraft(self): return ModelTypeACraft() class ModelTypeBCraftFactory(CraftProgrammingFactory): def creatCraft(self): return ModelTypeBCraft() class ModelTypeAChildCraftFactory(CraftProgrammingFactory): def creatCraft(self): return ModelTypeACraft(childModelType=True) cf = ModelTypeACraftFactory() c = cf.creatCraft() c.setStep([])
優點:
每一個具體產品對應一個具體工廠類,不需要修改工廠類的程式碼
隱藏了物件建立的實現細節
缺點:
每增加一個具體的產品,就必須增加一個對應的具體工廠類
抽象工廠模式
定義:一個工廠類介面,讓工廠子類建立一系列相關或互相依賴的物件
相比於工廠模式方法,抽象工廠模式中的每一個具體工廠都生產了一套產品
例子:我們延續上面的染色機工藝程式設計的例子,一個工藝我們分為工步、引數、工步型別
from abc import ABCMeta, abstractmethod #抽象產品 class CraftParameter(metaclass=ABCMeta): #abstract class @abstractmethod def setParameter(self): pass class CraftStep(metaclass=ABCMeta): #abstract class @abstractmethod def setStep(self,step: list): pass class CraftFuntionType(metaclass=ABCMeta): #abstract class @abstractmethod def setFuntionType(self,funcType: int): pass #抽象工廠 class CreatCraftFactory(metaclass=ABCMeta): @abstractmethod def creatParameter(self): pass @abstractmethod def creatStep(self): pass @abstractmethod def creatFuntionType(self): pass #具體產品 class ModelTypeACraftParameter(CraftParameter): def setParameter(self): print("A機型工藝的引數") class ModelTypeACraftStep(CraftStep): def setStep(self,step: list): print(f"A機型工藝的工步{step}") class ModelTypeACraftFuntionType(CraftFuntionType): def setFuntionType(self,funcType: int): print(f"A機型工藝的工步型別{funcType}") #具體工廠 class ModelTypeACreatCraftFactory(CreatCraftFactory): def creatParameter(self): return ModelTypeACraftParameter() def creatStep(self): return ModelTypeACraftStep() def creatFuntionType(self): return ModelTypeACraftFuntionType() #客戶端 class Craft: def __init__(self,parameter,step,funtionType): self.parameter = parameter self.step = step self.funtionType = funtionType def craft_info(self): self.parameter.setParameter() self.step.setStep([]) self.funtionType.setFuntionType(1) def creatCraft(factory): parameter = factory.creatParameter() step = factory.creatStep() funtionType = factory.creatFuntionType() return Craft(parameter,step,funtionType) c1 = creatCraft(ModelTypeACreatCraftFactory()) c1.craft_info()
優點:
客戶端與類具體實現分離
每個工廠都有一個完成的產品系列,易於交換產品系列和產品一致性
缺點:
難以支援新的抽象產品
單例模式
定義:保證一個類只有一個例項,並提供一個訪問他的全域性訪問點
角色:singleton
優點:
對唯一例項受控訪問
單例相當於全域性變數,防止名稱空間被汙染
常用於日誌、資料庫等
class Singleton: def __new__(cls, *args, **kwargs): if not hasattr(cls,"_instance"): cls._instance = super().__new__(cls) return cls._instance class MyClass(Singleton): def __init__(self,a): self.a = a a=MyClass(10) b=MyClass(20) print(a.a) #20 print(b.a) #20 print(id(a) , id(b)) #id相同
介面卡模式
定義:將一個類介面轉換成客戶希望的另一個介面。介面卡使得原來介面不相容的現在可以一起工作
類介面卡:使用類的繼承
物件介面卡:使用組合
from abc import ABCMeta, abstractmethod class CraftParameter(metaclass=ABCMeta): #abstract class @abstractmethod def setParameter(self): pass class ModelACraftParameter(CraftParameter): def setParameter(self): print("A機型的工藝引數") class ModelBCraftParameter(CraftParameter): def setParameter(self): print("B機型的工藝引數") class ModelCCraftParameter: def insertParameter(self): print("C機型的工藝引數") #這個時候我們發現C機型方法和A、B機型的方法不一致,我們需要去適配C機型 #第一種方法:類介面卡 class NewModelCraftParameter(CraftParameter,ModelCCraftParameter): def setParameter(self): self.insertParameter() #第二種辦法:物件介面卡 class CraftParameterAdapter: def __init__(self,craftParameter): self.craftParameter = craftParameter def setParameter(self): self.craftParameter().insertParameter() # c=NewModelCraftParameter() # c.setParameter() c=CraftParameterAdapter(ModelCCraftParameter) c.setParameter()
橋模式
角色:
抽象
細化抽象
實現者
具體實現者
場景:當事務有兩個以上維度,兩個維度都可以擴充
優點:
抽象和實現分離
具有優秀的擴充能力
from abc import ABCMeta, abstractmethod #抽象 class Shape(metaclass=ABCMeta): def __init__(self,color): self.color = color @abstractmethod def draw(self): pass #實現者 class Color(metaclass=ABCMeta): @abstractmethod def paint(self,shape): pass #細化抽象 class Triangle(Shape): name = "三角形" def draw(self): self.color.paint(self) class Circle(Shape): name = "三角形" def draw(self): self.color.paint(self) #具體實現者 class Red(Color): def paint(self,shape): print(f"紅色的{shape.name}") shape = Triangle(Red()) shape.draw()
組合模式
適用於:部分--整體結構
優點:
包含了基本物件和組合物件的類層次結構
簡化客戶端程式碼,可以一致的使用組合物件和單個物件
更容易增加新型別元件
from abc import ABCMeta, abstractmethod #抽象元件 class ModelType(metaclass=ABCMeta): @abstractmethod def printModelType(self): pass #葉子元件最小的節點 class SonModel(ModelType): def __init__(self, modelName): self.modelName = modelName def __str__(self): return f"機型{self.modelName}" def printModelType(self): print(self) class ParentModelType(ModelType): def __init__(self,parentModelType,model): self.parentModelType = parentModelType self.model = model def __str__(self): return f"{self.parentModelType}旗下的[{self.model}]" def printModelType(self): print(self) #複合元件 class Brand(ModelType): def __init__(self, iterable): self.sonModel = [m for m in iterable] def printModelType(self): for i in self.sonModel: i.printModelType() # p = ParentModelType("setex757",SonModel("水流-02")) # p.printModelType() s1 = SonModel("水流-02") p1 =ParentModelType("setex757",s1) b = Brand([s1,p1]) b.printModelType()
外觀模式
比較簡單:高層程式碼不需要知道低層程式碼,只需要用封裝好的就行
定義:為子系統的介面提空一個一致的介面,定義一個高層介面,這介面使得系統更容易使用
角色:
外觀
子系統類
優點:
減少系統依賴
提高靈活性
提高安全性
class LendingSinger: def start(self): print("主唱開始唱") def stop(self): print("主唱閉嘴") class Bass: def start(self): print("貝斯開始演奏") def stop(self): print("貝斯停止演奏") class Keyboard: def start(self): print("鍵盤手開始演奏") def stop(self): print("鍵盤手停止演奏") #更高階級別的類:樂隊 #通過高系統呼叫來封裝子系統 class Band: def __init__(self): self.lengdingSinger = LendingSinger() self.bass = Bass() self.keyboard = Keyboard() def start(self): self.bass.start() self.lengdingSinger.start() self.keyboard.start() def stop(self): self.keyboard.stop() self.bass.stop() self.lengdingSinger.stop() b=Band() b.start() b.stop()
模板方法模式
定義:先寫一個骨架,其中的一些細節可以延遲實現,模板方法可以使得子類不改變骨架就可以重新定義某些改變
角色:
抽象類:定義原子操作(或者叫鉤子操作),實現一個模板方法骨架
具體類:實現原子操作
依舊拿上面的樂隊作為例子
from abc import ABCMeta , abstractmethod from time import sleep class Band: @abstractmethod def lengdingSinger(self): pass @abstractmethod def bass(self): pass @abstractmethod def keyboard(self):#原子操作 pass def run(self): #模板方法 self.bass() while True: try: self.lengdingSinger() sleep(1) except KeyboardInterrupt: break self.keyboard() #原子操作定義好,等後面在子類裡面實現 class NewBand(Band): def lengdingSinger(self): print("主唱無伴奏solo") def bass(self): print("貝斯進") def keyboard(self): print("鍵盤手進") b = NewBand().run()