單例模式
懶漢式
class SingleTon:# 類屬性_obj = None # 用來存儲對象# 創造對象def __new__(cls, *args, **kwargs):# 如果對象不存在,就創造一個對象if cls._obj is None:cls._obj = super().__new__(cls, *args, *kwargs)# 返回對象return cls._objif __name__ == '__main__':obj_1 = SingleTon() # 創造一個對象obj_2 = SingleTon() # 再次創造一個對象print("obj_1的內存地址:", id(obj_1)) # obj_1的內存地址: 2801491317584print("obj_2的內存地址:", id(obj_2)) # obj_2的內存地址: 2801491317584print(obj_1 is obj_2) # True
餓漢式
- test.py
class SingleTon:pass# 創建一個對象
obj = SingleTon# 提供接口
def get_instance():return obj
- main.py
from test import get_instanceif __name__ == '__main__':obj_1 = get_instance() # 創建一個對象obj_2 = get_instance() # 再創建一個對象print(obj_1 is obj_2) # True
工廠模式
簡單工廠模式
"""實現:簡單計算器(加減乘除)1. 提供一個抽象產品類2. 提供多個具體產品類3. 提供一個工廠類
"""from abc import ABC, abstractmethod# 計算器(抽象產品類)
class Calculator(ABC): # 繼承 ABC 抽象類def __init__(self):self.left_value = 0self.right_value = 0def set(self, left_value, right_value):self.left_value = left_valueself.right_value = right_valuereturn self@abstractmethoddef run(self): # 抽象方法pass# 加法計算器(具體產品類)
class AddCalculator(Calculator): # 繼承 Calculator 類def run(self):return self.left_value + self.right_value# 減法計算器(具體產品類)
class SubCalculator(Calculator): # 繼承 Calculator 類def run(self):return self.left_value - self.right_value# 乘法計算器(具體產品類)
class MulCalculator(Calculator): # 繼承 Calculator 類def run(self):return self.left_value * self.right_value# 除法計算器(具體產品類)
class DivCalculator(Calculator): # 繼承 Calculator 類def run(self):if self.right_value == 0:raise "除數不能為零!"return self.left_value / self.right_value# 工廠類
class Factory:@staticmethoddef produce_calculator(char): # 類方法match char:case "+":return AddCalculator() # 創建對象case "-":return SubCalculator() # 創建對象case "*":return MulCalculator() # 創建對象case "/":return DivCalculator() # 創建對象case _:raise "不支持其他的運算符!"if __name__ == '__main__':# 工廠生產4種類型的計算器產品add_calculator = Factory.produce_calculator("+") # 加法計算器sub_calculator = Factory.produce_calculator("-") # 減法計算器mul_calculator = Factory.produce_calculator("*") # 乘法計算器div_calculator = Factory.produce_calculator("/") # 除法計算器# 使用除法計算器res = div_calculator.set(10, 5).run() # 設置左值(被除數)和右值(除數),然后運行print(res) # 2.0
工廠方法模式
from abc import ABC, abstractmethod# 產品(抽象產品類)
class Product(ABC): # 繼承 ABC 抽象類# 抽象:此產品補充燃料的功能@abstractmethoddef fuel(self):pass# 抽象:此產品起飛的功能@abstractmethoddef fly(self):pass# 飛機(具體產品類)
class PlaneProduct(Product): # 繼承 Product 產品類# 實現:此產品補充燃料的功能def fuel(self):print(f"飛機-CS{id(self)},補充燃料中...")# 實現:此產品起飛的功能def fly(self):print(f"飛機-CS{id(self)},起飛!")# 火箭(具體產品類)
class RocketProduct(Product): # 繼承 Product 產品類# 實現:此產品補充燃料的功能def fuel(self):print(f"火箭-CS{id(self)},補充燃料中...")# 實現:此產品起飛的功能def fly(self):print(f"火箭-CS{id(self)},起飛!")# 工廠(抽象工廠類)
class Factory(ABC):# 抽象:生產產品@abstractmethoddef produce_product(self):pass# 飛機工廠(具體工廠類)
class PlaneFactory(Factory):# 具體:生產飛機產品def produce_product(self):return PlaneProduct() # 創建對象,并返回出去# 火箭工廠(具體工廠類)
class RocketFactory(Factory):# 具體:生產火箭產品def produce_product(self):return RocketProduct() # 創建對象,并返回出去# 演示
def work(factory):product = factory.produce_product() # 工廠生產產品product.fuel() # 使用產品的"補充燃料"功能product.fly() # 使用產品"飛行"的功能if __name__ == '__main__':# 創建一個飛機工廠plane_factory = PlaneFactory()# 讓飛機工廠干活work(plane_factory)# 創建一個火箭工廠rocket_factory = RocketFactory()# 讓火箭工廠干活work(rocket_factory)
抽象工廠模式
from abc import ABC, abstractmethod# 抽象產品
class Product(ABC):@abstractmethoddef show(self):pass# 抽象鍵盤產品
class KeyBoard(Product):@abstractmethoddef show(self):pass# 抽象鼠標產品
class Mouse(Product):@abstractmethoddef show(self):pass# 具體鍵盤產品1
class MikaKeyBoard(KeyBoard):def show(self):print("Mika鍵盤")# 具體鍵盤產品2
class PikiKeyBoard(KeyBoard):def show(self):print("Piki鍵盤")# 具體鼠標產品1
class MikaMouse(Mouse):def show(self):print("Mika鼠標")# 具體鼠標產品2
class PikiMouse(Mouse):def show(self):print("Piki鼠標")# 抽象工廠類
class Factory(ABC):@abstractmethoddef produce_keyboard(self):pass@abstractmethoddef produce_mouse(self):pass# 具體工廠1
class MikaFactory(Factory):def produce_keyboard(self):return MikaKeyBoard()def produce_mouse(self):return MikaMouse()# 具體工廠2
class PikiFactory(Factory):def produce_keyboard(self):return PikiKeyBoard()def produce_mouse(self):return PikiMouse()# 測試
def work(factory):keyborad = factory.produce_keyboard() # 工廠制作鍵盤mouse = factory.produce_mouse() # 工廠制作鼠標keyborad.show() # 查看鍵盤信息mouse.show() # 查看鼠標信息if __name__ == '__main__':# 創造Mika工廠,讓它運行工作factory = MikaFactory()work(factory)# 創建Piki工廠,讓它運行工作factory = PikiFactory()work(factory)
建造者模式
"""小明想要給自己的"戴爾"電腦外接一些設備:Mika鼠標、Piki鍵盤小花想要給自己的"聯想"電腦外接一些設備:Piki鼠標、Mika鍵盤1. 找到技術人員告訴需求2. 技術員工進行組裝3. 檢查組裝情況
"""from abc import ABC, abstractmethod# 組裝電腦(抽象)
class AssembleComputer(ABC):@abstractmethoddef install_mouse(self, brand): # 安裝鼠標(抽象)pass@abstractmethoddef install_keyboard(self, brand): # 安裝鍵盤(抽象)pass@abstractmethoddef show(self): # 查看組裝的狀態(抽象)pass# 組裝"戴爾"電腦(具體)
class AssembleDellComputer(AssembleComputer):def __init__(self):self.__installation_list = [] # 安裝列表,用來記錄當前已經成功安裝了的組件def install_mouse(self, brand):self.__installation_list.append(f"{brand}鼠標")print(f"已安裝:{brand}鼠標")def install_keyboard(self, brand):self.__installation_list.append(f"{brand}鍵盤")print(f"已安裝:{brand}鍵盤")def show(self):print("此電腦的所有外接設備:", end="")for item in self.__installation_list:print(item, end=", ")print()# 組裝"聯想"電腦(具體)
class AssembleLenovoComputer(AssembleComputer):def __init__(self):self.__installation_list = [] # 安裝列表,用來記錄當前已經成功安裝了的組件def install_mouse(self, brand):self.__installation_list.append(f"{brand}鼠標")print(f"已安裝:{brand}鼠標")def install_keyboard(self, brand):self.__installation_list.append(f"{brand}鍵盤")print(f"已安裝:{brand}鍵盤")def show(self):print("此電腦的所有外接設備:", end="")for item in self.__installation_list:print(item, end=", ")print()# 建造者(抽象)
class Builder(ABC):def __init__(self, computer_type):# self.product 里面保存(維護)著一個組裝對象if computer_type == "戴爾":self._product = AssembleDellComputer()elif computer_type == "聯想":self._product = AssembleLenovoComputer()else:raise "電腦類型錯誤!"@abstractmethoddef install_mouse(self, brand):pass@abstractmethoddef install_keyboard(self, brand):pass@abstractmethoddef check(self):pass# 建造者(具體)————技術人員
class Technician(Builder):# 技術人員安裝鼠標def install_mouse(self, brand):print(f"技術人員正在安裝{brand}鼠標...")self._product.install_mouse(brand)print(f"技術人員安裝{brand}鼠標成功!")# 技術人員安裝鍵盤def install_keyboard(self, brand):print(f"技術人員正在安裝{brand}鍵盤...")self._product.install_keyboard(brand)print(f"技術人員安裝{brand}鍵盤成功!")# 技術人員檢查安裝情況def check(self):print("技術人員正在檢查設備的安裝情況...")print("技術人員檢查完畢,安裝結果如下:")self._product.show()if __name__ == '__main__':# 創造一個負責組裝戴爾電腦的技術人員t1 = Technician("戴爾")# 創造一個負責組裝聯想電腦的技術人員t2 = Technician("聯想")# 小明告訴 t1 技術人員,組裝 Mika鼠標、Piki鍵盤,技術人員根據要求進行安裝t1.install_mouse("Mika")t1.install_keyboard("Piki")# 小花告訴 t2 技術人員,組裝 Piki鼠標、Mika鍵盤,技術人員根據要求進行安裝t2.install_mouse("Piki")t2.install_keyboard("Mika")# t1 技術人員檢查組裝情況t1.check()# t2 技術人員檢查組裝情況t2.check()
原型模式
import copy # 導入copy模塊,用于深度復制對象# 定義一個名為 Prototype(原型)的類,用于管理對象的注冊、注銷和克隆
class Prototype:def __init__(self):self._objects = {} # 初始化一個字典來存儲注冊的對象,鍵為名稱,值為對象實例def register_object(self, name, obj):""" 注冊一個對象到_objects字典中 :param name: 對象的名稱 :param obj: 要注冊的對象實例 """self._objects[name] = objdef unregister_object(self, name):""" 從_objects字典中注銷一個對象 :param name: 要注銷的對象的名稱 """del self._objects[name]def clone(self, name, **attr):""" 克隆一個已注冊的對象,并更新其內部屬性字典 :param name: 要克隆的對象的名稱 :param attr: 要更新的屬性字典,使用關鍵字參數傳入 :return: 克隆并更新后的對象實例 """obj = copy.deepcopy(self._objects.get(name)) # 使用deepcopy進行深度復制,得到一個新的對象實例obj.__dict__.update(attr) # 更新對象的__dict__屬性,即更新其內部屬性。 attr == {'a': 1, 'b': 2, 'c': 3}return objdef test():# 定義一個類A,用于演示class A:def __str__(self):return "I am A"# 創建A的一個實例aa = A()# 創建一個Prototype實例,用于管理對象prototype = Prototype()# 將a注冊到prototype中,名稱為'a'prototype.register_object('a', a)# 克隆a并更新其內部屬性,得到bb = prototype.clone('a', a=1, b=2, c=3)# 打印a的字符串表示print(a)# 打印b的內部屬性字典print(b.__dict__)# 嘗試打印b的屬性a, b, cprint(b.a)print(b.b)print(b.c)if __name__ == '__main__':test()
補充說明:
-
原型模式(Prototype Pattern)是一種創建型設計模式,它允許一個對象通過復制其自身的內部狀態來創建新的對象實例。
-
這種復制過程可以被稱為“克隆”。
-
原型模式提供了一種不依賴于類的構造函數來創建對象實例的方式,而是使用現有的對象實例來創建新的對象。
原型模式的作用:
- 性能優化:當對象的創建過程非常復雜或者代價非常高時,使用原型模式可以避免重復執行這些復雜的操作,從而提高性能。通過克隆一個已經存在的對象,可以快速地生成新的對象實例。
- 避免子類的構造函數被頻繁調用:在繼承層次較深的場景下,頻繁地調用子類的構造函數可能會帶來性能問題。通過原型模式,可以避免這種情況,因為對象的創建是通過克隆來完成的。
- 動態擴展:由于原型模式允許在運行時動態地添加或刪除對象,因此它可以支持動態擴展。這意味著可以根據需要動態地改變系統中對象的數量或類型。
- 簡化對象創建:當對象創建涉及復雜的配置或設置時,原型模式可以提供一個更簡單的創建對象的方式。通過克隆一個已經配置好的對象實例,可以快速地生成具有相同配置的新對象。
示例代碼中的原型模式:
- 在示例代碼中,
Prototype
類就是一個原型管理器的實現。 - 它維護了一個存儲已注冊對象的字典(
_objects
)。 - 通過
register_object()
方法可以將對象注冊到字典中,通過unregister_object()
方法可以從字典中注銷對象。 clone()
方法則用于克隆已注冊的對象,并允許通過關鍵字參數來更新克隆對象的屬性。- 這個示例代碼中的
A
類是一個簡單的類,用于演示原型模式的使用。 - 通過創建一個
A
類的實例a
,并將其注冊到Prototype
實例中,然后調用clone()
方法來克隆a
并更新其屬性,可以得到一個新的對象實例b
。 - 這個過程中,
a
和b
是獨立的對象實例,但它們具有相同的初始狀態(因為b
是a
的克隆),并且b
的屬性可以被單獨更新。
總結
創建型模式總結
- 單例模式:創建一個全局的對象
- 工廠方法模式:實現單個類的對象的創建
- 抽象工廠模式:實現多個類的對象的創建
- 建造者模式:實現復雜類的對象的創建
- 原型模式:實現自身類的克隆