策略模式和模板模式 18/30 | Python 主题月
写在前面
本文正在参加「Python主题月」,详情查看活动链接
这个月是 Python 活动月,我决定尝试用 Python 来刷这 30 天的每日一题和随机一题。然后如果周末有精力,我想捣鼓捣鼓这个python-patterns
设计模式对我来说更多的是学习而不是我的个人经验总结,所以我很可能理解偏,如果有大佬见到了请及时指出,我之所以选择在掘金来写一些个人的东西是因为这里的文章质量更高,我不希望后来者看到了这些文章被误导。
策略模式
from __future__ import annotations
from typing import Callable, Type
class DiscountStrategyValidator: # Descriptor class for check perform
@staticmethod
def validate(obj: Order, value: Callable) -> bool:
try:
if obj.price - value(obj) < 0:
raise ValueError(
f"Discount cannot be applied due to negative price resulting. {value.__name__}"
)
except ValueError as ex:
print(str(ex))
return False
else:
return True
def __set_name__(self, owner, name: str) -> None:
self.private_name = f"_{name}"
def __set__(self, obj: Order, value: Callable = None) -> None:
if value and self.validate(obj, value):
setattr(obj, self.private_name, value)
else:
setattr(obj, self.private_name, None)
def __get__(self, obj: object, objtype: Type = None):
return getattr(obj, self.private_name)
class Order:
discount_strategy = DiscountStrategyValidator()
def __init__(self, price: float, discount_strategy: Callable = None) -> None:
self.price: float = price
self.discount_strategy = discount_strategy
def apply_discount(self) -> float:
if self.discount_strategy:
discount = self.discount_strategy(self)
else:
discount = 0
return self.price - discount
def __repr__(self) -> str:
return f"<Order price: {self.price} with discount strategy: {getattr(self.discount_strategy,'__name__',None)}>"
def ten_percent_discount(order: Order) -> float:
return order.price * 0.10
def on_sale_discount(order: Order) -> float:
return order.price * 0.25 + 20
def main():
"""
>>> order = Order(100, discount_strategy=ten_percent_discount)
>>> print(order)
<Order price: 100 with discount strategy: ten_percent_discount>
>>> print(order.apply_discount())
90.0
>>> order = Order(100, discount_strategy=on_sale_discount)
>>> print(order)
<Order price: 100 with discount strategy: on_sale_discount>
>>> print(order.apply_discount())
55.0
>>> order = Order(10, discount_strategy=on_sale_discount)
Discount cannot be applied due to negative price resulting. on_sale_discount
>>> print(order)
<Order price: 10 with discount strategy: None>
"""
if __name__ == "__main__":
import doctest
doctest.testmod()
模板模式
def get_text():
return "plain-text"
def get_pdf():
return "pdf"
def get_csv():
return "csv"
def convert_to_text(data):
print("[CONVERT]")
return f"{data} as text"
def saver():
print("[SAVE]")
def template_function(getter, converter=False, to_save=False):
data = getter()
print(f"Got `{data}`")
if len(data) <= 3 and converter:
data = converter(data)
else:
print("Skip conversion")
if to_save:
saver()
print(f"`{data}` was processed")
def main():
"""
>>> template_function(get_text, to_save=True)
Got `plain-text`
Skip conversion
[SAVE]
`plain-text` was processed
>>> template_function(get_pdf, converter=convert_to_text)
Got `pdf`
[CONVERT]
`pdf as text` was processed
>>> template_function(get_csv, to_save=True)
Got `csv`
Skip conversion
[SAVE]
`csv` was processed
"""
if __name__ == "__main__":
import doctest
doctest.testmod()
小结
参考文献
- 无