|
发表于 2022-10-21 17:35:40
|
显示全部楼层
你的问题中Order这个类的total可以写成函数形式,也可以写成self.total的形式,就像前面的人说的那样。
而且看了你的代码我觉得有些问题,你虽然使用了ABC进行抽象,但是似乎自己都没有规划好每个接口应该具备怎样的能力。从设计模式的角度来说,你虽然使用了接口,但是却违背了里氏替换原则和依赖倒置原则。所以我把你的代码顺序进行了大幅改动,逻辑微调(就是Order类的total方法那个部分),保留了你要的total,也删除了__total这个私有属性,希望修改后的代码能对你有用。另外请注意,我使用了Python 3.10中的新特性来标注参数类型与返回值类型:- from abc import ABCMeta, abstractmethod
- from collections import namedtuple
- # ----------抽象层,定义各种接口----------
- Customer = namedtuple('Customer', 'name fidelity')
- class InterfaceItem(metaclass=ABCMeta):
- """商品接口,子类须具备product、price、quantity属性,
- 必须实现total方法
- """
- product: str
- price: int | float
- quantity: int | float
- @abstractmethod
- def total(self) -> int | float:
- """商品总价"""
- pass
- class InterfaceOrder(metaclass=ABCMeta):
- """订单接口,子类须具备cart、customer、total属性,
- 且必须实现due方法
- """
- cart: list[InterfaceItem]
- customer: Customer
- @property
- @abstractmethod
- def total(self) -> int | float:
- """订单商品的总金额"""
- pass
- @abstractmethod
- def due(self) -> int | float:
- """应该支付金额"""
- pass
- class InterfacePromotion(metaclass=ABCMeta):
- """促销活动接口,子类必须实现discount方法"""
- @abstractmethod
- def discount(self, order: InterfaceOrder) -> int | float:
- """返回折扣金额(正值)"""
- pass
- # ----------实现层,实现各种接口----------
- class LineItem(InterfaceItem):
- """具体商品,实现IterfaceItem接口"""
- def __init__(
- self,
- product: str,
- quantity: int | float,
- price: int | float
- ) -> None:
- self.product = product
- self.quantity = quantity
- self.price = price
- def total(self) -> int | float:
- return self.price * self.quantity
- class Order(InterfaceOrder):
- """具体订单,实现IterfaceOrder接口"""
- def __init__(
- self,
- customer: Customer,
- *cart: InterfaceItem,
- promotion: InterfacePromotion = None
- ) -> None:
- self.customer = customer
- self.cart = list(cart)
- self.promotion = promotion
- @property
- def total(self) -> int | float:
- if self.cart:
- return sum(item.total() for item in self.cart)
- return 0
- def due(self) -> int | float:
- if self.promotion is None:
- discount = 0
- else:
- discount = self.promotion.discount(self)
- return self.total - discount
- def __repr__(self):
- fmt = '<Order total: {:.2f} due: {:.2f}>'
- return fmt.format(self.total, self.due())
- class FidelityPromo(InterfacePromotion):
- """为积分为1000或以上的顾客提供%5的折扣"""
- def discount(self, order: InterfaceOrder) -> int | float:
- return order.total * .05 if order.customer.fidelity >= 1000 else 0
- class BulkItemPromo(InterfacePromotion):
- """单个商品为20个以上时提供10%折扣"""
- def discount(self, order: InterfaceOrder) -> int | float:
- discount = 0
- for item in order.cart:
- if item.quantity >= 20:
- discount += item.total() * .1
- return discount
- class LargeOrderPromo(InterfacePromotion):
- """订单中的不同商品达到10个以上时提供7%折扣"""
- def discount(self, order: InterfaceOrder) -> int | float:
- distinct_items = {item.product for item in order.cart}
- if len(distinct_items) >= 10:
- return order.total * .07
- return 0
- # ----------业务层,处理具体业务逻辑----------
- def business() -> None:
- # 实例化各种促销方案
- fp: InterfacePromotion = FidelityPromo()
- c1: Customer = Customer('张三', 1000)
- goods: list[InterfaceItem] = [
- LineItem('商品A', 20, 126), LineItem('商品B', 11, 51.8), LineItem('商品C', 3, 26)
- ]
- order: Order = Order(c1, *goods, promotion=fp)
- print(order)
- if __name__ == '__main__':
- business()
复制代码 |
|