天天看點

裝飾器器模式(Decorator Design Pattern)及代碼實作

什麼是 裝飾器模式?

動态的 給某個對象添加額外的功能;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