面向對象設計原則和模式
- 2022 年 7 月 9 日
- 筆記
面向對象設計原則
開放封閉原則:
一個軟體實體如類、模組和函數應該對拓展開放,對修改關閉。即軟體實體應盡量在不修改原有程式碼的情況下進行擴展。
里氏替換原則:
所有引用的父類的地方必須能透明的使用其子類的對象
依賴倒置原則:
高層模組不應該依賴低層模組,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象;即針對介面編程,而不是針對實現編程
工廠方法模式
定義:創建對象的介面(工廠介面),讓子類決定實例化哪一個產品類
角色:
抽象工廠角色(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()