1. 程式人生 > 其它 >javaWeb 控制層互相呼叫的兩種方案

javaWeb 控制層互相呼叫的兩種方案

目錄

1. 裝飾器定義

裝飾器由名稱空間,函式物件,閉包函式組合而來

裝飾:給被裝飾物件新增額外的功能
器:指的是工具

裝飾器的原則:開放封閉原則
  開放:對擴充套件開放
  封閉:對修改封閉
    
裝飾器核心思想:在不改變被"裝飾物件內部程式碼"和"原有呼叫方式"的基礎上新增額外的功能
  
eg:
  import time
  def index():
      time.sleep(3)  # 阻塞3秒
      print('form index')
  start_time = time.time()  # 記錄函式執行之前的時間戳(1970年1月1日開始計算的秒數)
  index()  # 呼叫函式
  end_time = time.time()  # 記錄函式執行之後的時間戳
  print(end_time - start_time)  # 計算出函式執行的時間值

2. 裝飾器簡易版

給函式新增統計執行時間的功能

import time
def run_time(func):
    def r_time():
        start_time = time.time()
        func()
        end_time = time.time()
        print('程式執行時間為%s' % (end_time - start_time))
    return r_time
def for_loop():
    for i in range(100000):
        pass
def while_loop():
    i = 0
    while i < 100000:
        i += 1
for_loop = run_time(for_loop)  # 左側的for_loop其實是r_time函式名,賦值給一個叫for_loop的變數名
for_loop()  # 只是在使用上感覺還是原來的函式名
while_loop = run_time(while_loop)
while_loop()

3. 裝飾器引數問題

import time
def outer(func):
    def run_time(*args, **kwargs):  # 將傳入的位置引數組織成元組,關鍵字引數組織成字典
        start_time = time.time()
        func(*args, **kwargs)  # 將組織成元組的引數進行拆分成位置引數,將組織成字典的引數拆分成關鍵字引數
        end_time = time.time()
        print("程式執行時間%s" % (end_time - start_time))
    return run_time
def get_name(name):
    time.sleep(1)
    print("from index name is %s" % name)
def get_age(age):
    time.sleep(1)
    print("from func age is %s" % age)

get_name = outer(get_name)
get_name('jason')
get_age = outer(get_age)
get_age(18)

4. 裝飾器返回值問題

def outer(func):
    def run_time(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # res用於接收被裝飾函式的返回值
        end_time = time.time()
        print("程式執行時間%s" % (end_time - start_time))
        return res  # 此時run_time函式的返回值就是被裝飾函式的返回值了
    return run_time
def num_max(a, b):
    time.sleep(1)
    if a > b:
        return a
    else:
        return b
num_max = outer(num_max)
print(num_max(11, 22))

5. 認證裝飾器

小功能實現

# 每次執行都校驗使用者名稱和密碼
def login(func):
    def auth():
        username = input('username:').strip()
        passwd = input('passwd:').strip()
        if username == 'jason' and passwd == '123':
            func()
        else:
            print("認證失敗")
    return auth
def func1():
    print("功能1")
def func2():
    print("功能2")
    
func1 = login(func1)
func1()

func2 = login(func2)
func2()
# 記錄使用者登入狀態,只需要認證一次
login_flag = {'flag': False}  # 資料為可變型別,則函式名稱空間內可以進行修改

def login(func):
    def auth():
        if login_flag.get('flag'):
            func()
        else:
            username = input("username:").strip()
            passwd = input("passwd:").strip()
            if username == 'jason' and passwd == '123':
                func()
                login_flag['flag'] = True
            else:
                print("認證失敗")
    return auth
def func1():
    print("功能1")
def func2():
    print("功能2")

func1 = login(func1)
func1()

func2 = login(func2)
func2()

6. 裝飾器固定模板

def outer(func):
    def inner(*args, **kwargs):
        print('執行函式之前可以新增的額外功能')
        res = func(*args, **kwargs)  # 執行被裝飾的函式
        print('執行函式之後可以新增的額外功能')
        return res  # 將被裝飾函式執行之後的返回值返回
    return inner

7. 裝飾器語法糖

def outer(func):
    def inner(*args, **kwargs):
        print('執行函式之前可以新增的額外功能')
        res = func(*args, **kwargs)  # 執行被裝飾的函式
        print('執行函式之後可以新增的額外功能')
        return res  # 將被裝飾函式執行之後的返回值返回
    return inner
@outer  # index = outer(index)
def index(*args, **kwargs):
    print('from index')
@outer  # home = outer(home)
def home():
    print('from home')
    
"""
裝飾器語法糖書寫規範
    語法糖必須緊貼在被裝飾物件的上方
裝飾器語法糖內部原理
    會自動將下面緊貼著的被裝飾物件名字當做引數傳給裝飾器函式呼叫
"""

8. 裝飾器雙層語法糖

# 帶引數帶返回值的雙層裝飾器
login_flag = {'flag': False}
def all_time(func):
    def run_time(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # 接收的返回值是func1和func2的
        end_time = time.time()
        print("程式執行時間%s" % (end_time - start_time))
        return res  
    return run_time
def login(func):
    def auth(*args, **kwargs):
        if login_flag.get('flag'):
            res = func(*args, **kwargs)
            return res
        else:
            username = input("username:").strip()
            passwd = input("passwd:").strip()
            if username == 'jason' and passwd == '123':
                res = func(*args, **kwargs)  # 接收的返回值run_time的
                login_flag['flag'] = True
                return res
            else:
                print("使用者名稱或密碼錯誤")
    return auth

@all_time
@login
def func1(name):
    print("功能1%s" % name)
    time.sleep(1)
    return '功能1->%s' % name

@all_time
@login
def func2(name):
    print("功能2%s" % name)
    time.sleep(1)
    return '功能2->%s' % name

print(func1('購物'))
print(func2('付款'))

9. 裝飾器三層語法糖

# 判斷七句print執行順序
def outter1(func1):
    print('載入了outter1')
    def wrapper1(*args, **kwargs):
        print('執行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1
    return wrapper1

def outter2(func2):
    print('載入了outter2')
    def wrapper2(*args, **kwargs):
        print('執行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2
    return wrapper2

def outter3(func3):
    print('載入了outter3')
    def wrapper3(*args, **kwargs):
        print('執行了wrapper3')
        res3 = func3(*args, **kwargs)
        return res3
    return wrapper3


@outter1
@outter2
@outter3
def index():
    print('from index')
    
# 載入了outter3
# 載入了outter2
# 載入了outter1
# 執行了wrapper1
# 執行了wrapper2
# 執行了wrapper3
# from index

10. 裝飾器修復技術

from functools import wraps
def outer(func):
    @wraps(func)  # 修復技術就是為了讓被裝飾物件更加不容易被察覺裝飾了
    def inner(*args, **kwargs):
        print('執行函式之前可以新增的額外功能')
        res = func(*args, **kwargs)  # 執行被裝飾的函式
        print('執行函式之後可以新增的額外功能')
        return res  # 將被裝飾函式執行之後的返回值返回
    return inner

@outer  # index = outer(index)
def index():
    print('from index')
print(index)
help(index)

def home():
    """這是一個home函式"""
    print('from home')
    
# help(index)
# help(home)
# print(index)
# help(len)

11. 有參裝飾器

# 通過第三層傳值
def outer(source_data):
    # source_data = 'file'
    def login_auth(func):
        def auth(*args,**kwargs):
            # 2.校驗使用者名稱和密碼是否正確
            # 資料的校驗方式可以切換多種
            if source_data == 'file':
                # 從檔案中獲取使用者資料並比對
                print('file檔案獲取')
            elif source_data == 'MySQL':
                # 從MySQL資料庫中獲取資料比對
                print('MySQL資料庫獲取')
            elif source_data == 'postgreSQL':
                # 從postgreSQL資料庫中獲取資料對比
                print('postgreSQL資料庫獲取')
            else:
                print('使用者名稱或密碼錯誤 無法執行函式')
        return auth
    return login_auth

@outer('file')
def index():
    print('from index')
@outer('MySQL')
def home():
    print('from home')

index()
home()