什麼是 裝飾器模式?
動态的 給某個對象添加額外的功能;python中可以使用裝飾器 完成此模式; python裝飾器可以 給不同對象 添加相同的功能,甚至一個對象 添加多個裝飾器功能,使 其靈活比對;
而 一般 添加額外的功能的方法 如 繼承 會導緻子類的所有執行個體化對象都含有 額外功能,有時 我們并不想這樣; 或者 直接在 類中添加額外的功能方法,但是 這樣 不利于 其他對象的 功能複用;
生活中的例子:
- 比如 給 狙擊槍 通過 消音器 增加消音的功能;并且 消音功能 可以增加 到 不同種類的槍上(忽略消音器樣式不同)
- 給 各種 戰鬥機增加 隐身圖層功能;
代碼中的例子(何時該使用此模式):
- flask架構 路由表示 通過 如下方式(給每個 函數增加 路由比對的功能):
@app.route('/admin/login')
def admin_login():
return 'xxx'
該模式關鍵的角色:
- 被裝飾 對象
- 裝飾器
該模式的主要優缺點如下:
優點:
- 你無需建立新子類即可擴充對象的行為。
- 你可以在運作時添加或删除對象的功能。
- 你可以用多個裝飾封裝對象來組合幾種行為。
- 單一職責原則。 你可以将實作了許多不同行為的一個大類拆分為多個較小的類。 或者一個裝飾器 實作一個功能
缺點:
- 實作行為不受裝飾棧順序影響的裝飾比較困難。
示例代碼部分
通過 python裝飾器實作 及函數實作方式
# -*- coding: utf-8 -*-
"""
(C) Guangcai Ren
All rights reserved
create time '2020/11/3 09:56'
Usage:
裝飾器模式
"""
import time
from functools import wraps
def timing_decorator(func):
"""
計算 耗時 裝飾器
:param func:
:return:
"""
@wraps(func)
def timeing(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
print(f'{func.__name__} 耗時:{time.time() - start_time} s')
return result
return timeing
def log_decorator(func):
"""
記錄 日志 裝飾器
:param func:
:return:
"""
@wraps(func)
def log_recode(*args, **kwargs):
print(f'{func.__name__} 記錄日志')
return func(*args, **kwargs)
return log_recode
def calculate(a, b):
"""
相加 函數
:param a:
:param b:
:return:
"""
return a + b
@timing_decorator
@log_decorator
def equal(a, b):
"""
判斷是否相等
:param a:
:param b:
:return:
"""
return a == b
if __name__ == '__main__':
# 在 對 被裝飾 函數 的 包(比如第三方安裝包)無法進行修改時 使用此方式 增加額外功能
# 添加一個 裝飾器
cal = log_decorator(calculate)
res = cal(1, 1)
print(res)
# 添加多個 裝飾器
cal = timing_decorator(log_decorator(calculate))
res = cal(1, 1)
print(res)
print('*' * 10)
# 直接在被裝飾 函數 上添加裝飾器
res = equal(1, 1)
print(res)
總結:
裝飾器模式 在python語言中 可以通過 内置的 裝飾器 文法特性 高效快速的實作; 也可使用 繼承方式 實作 或 對象組合方式實作;
相關連結:
https://refactoringguru.cn/design-patterns/decorator
http://c.biancheng.net/view/1366.html