当前位置: 首页 > news >正文

一个电商场景串联23种设计模式:创建型、结构型和行为型

理解了!你希望有一个具体的项目案例,能够涵盖所有23种设计模式,并且将它们分类为创建型、结构型和行为型。这个需求非常好,能够帮助你从实际的应用场景理解每种设计模式的用法。

为了实现这个目标,我将为你设计一个电商系统,并将23种设计模式通过具体的功能需求应用到这个系统中。系统的功能包括订单管理、支付管理、商品管理、用户管理等,而设计模式将被应用到各个功能模块中。

一. 概念篇

🧠 电商系统的设计模式实现


创建型模式 (Creational Patterns)

这些模式帮助我们灵活地创建对象。创建型模式主要解决如何高效地创建对象,减少对象创建的复杂度。

  1. 单例模式(Singleton)

    • 用途:确保一个类只有一个实例,常用于配置管理类、数据库连接等。
    • 应用:支付管理器类,确保支付模块只有一个实例。
  2. 工厂方法模式(Factory Method)

    • 用途:定义一个用于创建对象的接口,允许子类决定实例化哪一个类。
    • 应用:创建不同类型的商品(如电子产品、衣服等)。
  3. 抽象工厂模式(Abstract Factory)

    • 用途:提供一个接口,用于创建一系列相关的对象,而无需指定它们的具体类。
    • 应用:创建不同类型的支付方式(如信用卡支付、支付宝支付)。
  4. 建造者模式(Builder)

    • 用途:通过一步步的构建,构造一个复杂的对象。
    • 应用:构建一个复杂的订单对象,包含商品、支付方式、送货方式等。
  5. 原型模式(Prototype)

    • 用途:通过复制现有的对象来创建新对象,而不需要重新创建。
    • 应用:克隆一个订单对象,用于修改或再次提交。

结构型模式 (Structural Patterns)

这些模式帮助我们简化对象之间的组合关系。结构型模式主要关注类和对象如何组织和组合,简化系统的结构。

  1. 适配器模式(Adapter)

    • 用途:使得原本由于接口不兼容而不能一起工作的类可以协同工作。
    • 应用:将不同的支付方式(如信用卡支付和支付宝支付)转换为统一的支付接口。
  2. 桥接模式(Bridge)

    • 用途:将抽象部分与实现部分分离,使它们可以独立地变化。
    • 应用:将支付方式和通知方式分离,可以独立改变支付和通知的实现。
  3. 装饰者模式(Decorator)

    • 用途:动态地给对象添加一些额外的职责,不影响其他对象。
    • 应用:对商品应用优惠或折扣,包装商品对象。
  4. 组合模式(Composite)

    • 用途:将对象组合成树形结构,表示“部分-整体”层次结构。
    • 应用:管理一个订单中的多个商品。
  5. 外观模式(Facade)

    • 用途:提供一个统一的接口,简化系统的使用。
    • 应用:为用户提供一个简化的订单支付、配送等操作的接口。
  6. 享元模式(Flyweight)

    • 用途:通过共享技术来支持大量的细粒度对象,减少内存占用。
    • 应用:商品的描述信息(如价格、名称)在多个订单中共享。
  7. 代理模式(Proxy)

    • 用途:为其他对象提供代理以控制对该对象的访问。
    • 应用:为支付功能提供一个代理类,控制支付流程的访问权限。

行为型模式 (Behavioral Patterns)

这些模式主要关注对象之间的交互和职责分配,确保系统中的对象能够协同工作。

  1. 责任链模式(Chain of Responsibility)

    • 用途:为请求创建一个处理链,沿着链传递,直到某个对象处理请求。
    • 应用:订单处理中的多个步骤(如库存检查、支付处理、发货处理)通过责任链模式进行处理。
  2. 命令模式(Command)

    • 用途:将请求封装成对象,从而允许用户对请求排队、记录日志、以及支持可撤销操作。
    • 应用:购物车中的每个操作(如添加商品、删除商品)封装为命令对象。
  3. 解释器模式(Interpreter)

    • 用途:给定一个语言,定义其文法,并解释句子。
    • 应用:订单中的一些复杂的价格计算规则,可以使用解释器模式进行处理。
  4. 迭代器模式(Iterator)

    • 用途:提供一种方法,顺序访问一个聚合对象中的各个元素,而不暴露该对象的内部结构。
    • 应用:遍历订单中的所有商品,并进行相应的操作(如价格计算)。
  5. 中介者模式(Mediator)

    • 用途:通过一个中介对象来简化多个对象之间的通信。
    • 应用:不同模块之间的交互(如支付、配送、库存管理)通过中介者模式协调。
  6. 备忘录模式(Memento)

    • 用途:在不暴露对象实现的情况下,捕获对象的内部状态,并在需要时恢复。
    • 应用:保存订单状态(如支付状态),以便在需要时恢复。
  7. 观察者模式(Observer)

    • 用途:当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。
    • 应用:当订单状态(如支付状态)变化时,通知相关的模块(如用户、配送部门)。
  8. 状态模式(State)

    • 用途:允许一个对象在其内部状态改变时改变其行为。
    • 应用:订单可以处于不同的状态(如“待支付”、“已支付”、“已发货”),每个状态的行为不同。
  9. 策略模式(Strategy)

    • 用途:定义一系列算法,将每个算法封装起来,并使它们可以互换。
    • 应用:根据用户选择的支付方式(如信用卡、支付宝等),选择不同的支付策略。
  10. 模板方法模式(Template Method)

  • 用途:定义一个操作中的算法框架,将一些步骤延迟到子类中去实现。
  • 应用:订单处理的过程可以定义模板方法,每个步骤的具体实现交给子类来完成。
  1. 访问者模式(Visitor)
  • 用途:表示一个作用于某对象结构中的各元素的操作,可以通过访问者来定义新的操作。
  • 应用:在订单中添加新的操作(如计算税费),而不改变订单的结构。

🧠 总结:

  • 创建型模式:专注于如何创建对象,减少对象创建的复杂性,提升系统的灵活性。
  • 结构型模式:通过组合和组织类和对象,使得系统更简洁、高效。
  • 行为型模式:专注于对象之间的交互,保证它们高效地协作。

二. 实现篇

设计模式总结:解决电商场景中的问题

在电商平台中,设计模式可以帮助解决各种架构、行为和交互问题。下面我们对每种设计模式进行总结,表达它们在电商场景中解决的具体问题,并简要描述它们如何解决这些问题。

1️⃣ 创建型设计模式 (Creational Patterns)

1. 单例模式 (Singleton)
  • 解决的问题:确保在电商系统中某些组件如支付处理器、日志记录器等全局只有一个实例,避免重复创建和状态共享。
  • 解决方法:通过提供一个静态方法get_instance()来创建和访问单一实例。
class PaymentProcessor:_instance = None  # 类变量,存储单例实例@staticmethoddef get_instance():# 如果实例不存在,则创建一个新的实例if not PaymentProcessor._instance:PaymentProcessor._instance = PaymentProcessor()return PaymentProcessor._instance  # 返回唯一的实例# 使用单例模式
payment_processor = PaymentProcessor.get_instance()  # 获取单例实例

注释

  • PaymentProcessor类用单例模式确保全局只有一个实例。
  • get_instance方法确保实例化PaymentProcessor时不会重复创建,返回同一个实例。

2. 工厂方法模式 (Factory Method)
  • 解决的问题:创建不同类型的支付方式时,避免硬编码,便于扩展新的支付方式。
  • 解决方法:定义一个工厂类,基于支付方式类型动态创建相应的支付对象。
class Payment:def process(self, amount):pass  # 声明一个接口,允许不同支付方式处理支付class CreditCardPayment(Payment):def process(self, amount):# 使用信用卡支付print(f"Paid {amount} via Credit Card")class PaymentFactory:@staticmethoddef create_payment(payment_type: str) -> Payment:# 根据不同支付类型返回不同的支付方式对象if payment_type == "credit_card":return CreditCardPayment()  # 返回信用卡支付实例else:raise ValueError("Unknown payment type")  # 如果支付类型未知,抛出异常# 创建支付方式实例
payment = PaymentFactory.create_payment("credit_card")  # 创建一个信用卡支付对象
payment.process(100)  # 执行支付操作

注释

  • PaymentFactory根据不同的支付方式返回不同的支付对象。
  • CreditCardPayment实现了Payment接口,具体处理信用卡支付。

3. 抽象工厂模式 (Abstract Factory)
  • 解决的问题:为不同平台(比如不同操作系统或支付渠道)提供统一的支付接口。
  • 解决方法:使用抽象工厂来提供一组相关对象(如不同支付方式的实现)。
from abc import ABC, abstractmethod# 定义支付的抽象工厂类
class PaymentFactory(ABC):@abstractmethoddef create_payment(self):pass  # 工厂类的抽象方法class CreditCardPaymentFactory(PaymentFactory):def create_payment(self):return CreditCardPayment()  # 返回信用卡支付对象 #【见上一模式代码】class PaymentClient:def __init__(self, factory: PaymentFactory):# 使用工厂来创建支付方式self.payment = factory.create_payment()# 使用抽象工厂模式
factory = CreditCardPaymentFactory()  # 创建信用卡支付工厂
client = PaymentClient(factory)  # 使用工厂创建支付方式
client.payment.process(200)  # 执行支付

注释

  • PaymentFactory定义了抽象的支付工厂接口。
  • CreditCardPaymentFactory是具体工厂类,用来创建信用卡支付对象。

4. 建造者模式 (Builder)【】
  • 解决的问题:订单的构建过程可能比较复杂,例如包含多个商品的订单,且不同的订单可能需要不同的参数。
  • 解决方法:使用建造者模式,通过链式调用逐步构建复杂的订单对象。
class Order:def __init__(self):self.items = []  # 商品列表self.payment = None  # 支付方式def add_item(self, item):self.items.append(item)  # 添加商品到订单def set_payment(self, payment):self.payment = payment  # 设置支付方式class OrderBuilder:def __init__(self):self.order = Order()  # 创建一个空的订单def add_item(self, item):self.order.add_item(item)  # 链式调用,添加商品return self  # 返回builder对象以便继续链式调用def set_payment(self, payment):self.order.set_payment(payment)  # 设置支付方式return self  # 返回builder对象def build(self):return self.order  # 返回构建完成的订单# 使用建造者模式构建订单
builder = OrderBuilder()
order = builder.add_item("Laptop").set_payment("Credit Card").build()  # 建造订单

注释

  • OrderBuilder允许通过链式调用一步步构建订单对象。
  • 最终通过build()方法返回完整的订单对象。

5. 原型模式 (Prototype)
  • 解决的问题:需要克隆订单对象或商品对象,避免重复构建相同对象,减少内存开销。
  • 解决方法:提供一个clone()方法来复制对象,而无需重新创建新实例。
import copyclass Order:def __init__(self, items=None):if items is None:self.items = []else:self.items = items  # 初始化订单的商品列表def clone(self):return copy.deepcopy(self)  # 深拷贝当前订单对象# 克隆一个订单
order1 = Order(["Laptop", "Phone"])  # 创建一个订单
order2 = order1.clone()  # 克隆订单
order2.items.append("Tablet")  # 修改克隆订单的商品

注释

  • Order类提供了clone()方法,可以克隆一个订单对象。
  • 使用copy.deepcopy来实现深拷贝,确保克隆的订单是独立的。

2️⃣ 结构型设计模式 (Structural Patterns)

6. 适配器模式 (Adapter)
  • 解决的问题:电商系统可能需要集成不同支付接口(如支付宝、微信支付、银行卡等),它们有不同的API,需要统一接口。
  • 解决方法:定义一个适配器模式,将不同支付API适配为统一接口,便于替换和扩展。
class Alipay:def make_payment(self, amount):print(f"Paid {amount} via Alipay")class PaymentAdapter:def __init__(self, alipay):self.alipay = alipay  # 适配Alipay对象def process(self, amount):self.alipay.make_payment(amount)  # 适配并调用Alipay的支付方法# 使用适配器模式
alipay = Alipay()
payment_adapter = PaymentAdapter(alipay)  # 创建适配器
payment_adapter.process(100)  # 调用适配器进行支付

注释

  • PaymentAdapterAlipay的支付方式适配为统一的接口。

7. 桥接模式 (Bridge)
  • 解决的问题:支付和通知功能可能分别依赖于不同的具体实现,但它们在业务流程中需要一起协调工作。
  • 解决方法:将支付和通知功能通过桥接模式分离,让它们各自独立变化而不影响彼此的实现。
class Payment:def __init__(self, notification):self.notification = notification  # 聚合通知方式对象def process(self, amount):print(f"Processing payment of {amount}")self.notification.notify()  # 调用通知方式class Notification:def notify(self):pass  # 抽象通知方法class EmailNotification(Notification):def notify(self):print("Sending email notification")  # 具体的通知实现# 使用桥接模式
payment = Payment(EmailNotification())  # 选择Email通知方式
payment.process(200)

注释

  • Payment类通过桥接模式实现支付与通知功能的分离,允许更灵活的组合。

8. 装饰者模式 (Decorator)
  • 解决的问题:电商系统中的支付方式可能会有折扣、优惠券等附加功能,这些功能可以动态增加到支付过程中。
  • 解决方法:通过装饰器模式,在支付对象基础上动态添加额外的行为(如折扣、赠品等)。
class Payment:def process(self, amount):pass  # 支付接口class CreditCardPayment(Payment):def process(self, amount):print(f"Paid {amount} via Credit Card")class PaymentWithDiscount(Payment):def __init__(self, payment, discount):self.payment = payment  # 传入原支付对象self.discount = discount  # 折扣信息def process(self, amount):amount_after_discount = amount * (1 - self.discount)print(f"After discount: {amount_after_discount}")self.payment.process(amount_after_discount)  # 调用原支付对象# 使用装饰者模式
payment = PaymentWithDiscount(CreditCardPayment(), 0.1)  # 包装为带折扣的支付
payment.process(500)

注释

  • PaymentWithDiscount是一个装饰者,它在原支付方法上增加了折扣功能。

9. 组合模式 (Composite)
  • 解决的问题:订单由多个商品组成,有些商品可能是单独购买的,有些可能是套餐,组合模式帮助统一管理和操作这些商品。
  • 解决方法:通过组合模式将多个商品或套餐包装成一个订单对象,统一处理。
class Product:def __init__(self, name, price):self.name = nameself.price = priceclass Order:def __init__(self):self.products = []  # 商品列表def add_product(self, product):self.products.append(product)  # 添加商品到订单def total_price(self):return sum([product.price for product in self.products])  # 计算总价格# 使用组合模式
order = Order()
order.add_product(Product("Laptop", 1000))
order.add_product(Product("Phone", 500))
print(f"Total price: {order.total_price()}")

注释

  • OrderProduct实现了组合模式,通过Order类可以添加多个Product,计算总价格。

10. 外观模式 (Facade)
  • 解决的问题:电商系统中的支付、配送、订单管理等功能非常复杂,用户需要一个简化的接口来处理这些操作。
  • 解决方法:使用外观模式,提供一个简单的接口来整合多个复杂子系统(如支付、物流、订单处理)。
class PaymentFacade:def __init__(self, payment_processor, notification_service):self.payment_processor = payment_processorself.notification_service = notification_servicedef make_payment(self, amount):self.payment_processor.process_payment(amount)self.notification_service.send_notification(f"Payment of {amount} processed.")# 使用外观模式
payment_facade = PaymentFacade(PaymentProcessor(), EmailNotification())
payment_facade.make_payment(300)

注释

  • PaymentFacade封装了复杂的支付和通知流程,提供简化接口。

11. 享元模式 (Flyweight)
  • 解决的问题:商品信息可能会被多次共享,尤其是在库存管理中,重复的商品信息占用内存过多。
  • 解决方法:使用享元模式来共享相同的商品信息对象,只保留必要的状态(如库存数量等)。
class Product:def __init__(self, name, price):self.name = nameself.price = priceclass ProductFactory:_products = {}@staticmethoddef get_product(name, price):if name not in ProductFactory._products:ProductFactory._products[name] = Product(name, price)return ProductFactory._products[name]# 使用享元模式
product1 = ProductFactory.get_product("Laptop", 1000)
product2 = ProductFactory.get_product("Laptop", 1000)  # Reuses existing object

注释

  • ProductFactory共享相同的Product实例,减少内存消耗。

12. 代理模式 (Proxy)
  • 解决的问题:电商系统中支付的处理可能涉及到外部系统,需要增加代理来进行控制和优化,比如检查支付安全性。
  • 解决方法:代理模式通过一个中间层处理支付请求,检查权限、安全性等,控制访问。
class PaymentProxy:def __init__(self, payment_processor):self.payment_processor = payment_processordef process_payment(self, amount):if self.check_fraud(amount):self.payment_processor.process_payment(amount)else:print("Payment blocked due to fraud")def check_fraud(self, amount):return amount < 10000  # Fraud check# 使用代理模式
payment_proxy = PaymentProxy(PaymentProcessor())
payment_proxy.process_payment(5000)

注释

  • PaymentProxy在实际支付之前进行处理,比如进行欺诈检查。

3️⃣ 行为型设计模式 (Behavioral Patterns)

13. 责任链模式 (Chain of Responsibility)
  • 解决的问题:订单的审批过程可能涉及多个环节(例如库存检查、支付验证、配送确认等),每个环节依赖前一个环节的结果。
  • 解决方法:通过责任链模式,将每个处理环节组成链条,处理一个环节后自动传递给下一个环节。
class PaymentHandler:def __init__(self, successor=None):self.successor = successordef handle(self, amount):if self.successor:self.successor.handle(amount)class FraudHandler(PaymentHandler):def handle(self, amount):if amount > 10000:print("Fraud detected")else:super().handle(amount)class PaymentProcessorHandler(PaymentHandler):def handle(self, amount):print(f"Payment of {amount} processed")# 使用责任链模式
handler = FraudHandler(PaymentProcessorHandler())
handler.handle(15000)

注释

  • FraudHandlerPaymentProcessorHandler通过责任链模式处理支付请求。

14. 命令模式 (Command)
  • 解决的问题:电商系统可能需要将不同的业务操作(如支付、取消订单)封装成对象,便于回滚、重试等。
  • 解决方法:命令模式将每个操作封装成对象,并可以对这些对象进行排队、执行、撤销等操作。
class Command:def execute(self):passclass PaymentCommand(Command):def __init__(self, payment_processor, amount):self.payment_processor = payment_processorself.amount = amountdef execute(self):self.payment_processor.process_payment(self.amount)# 使用命令模式
command = PaymentCommand(PaymentProcessor(), 500)
command.execute()

注释

  • PaymentCommand封装了支付请求,允许在后续执行或撤销。

15. 解释器模式 (Interpreter)
  • 解决的问题:电商系统可能需要处理复杂的优惠规则表达式(例如满减、折扣等)。
  • 解决方法:使用解释器模式解析和执行这些规则表达式,将其转换为具体的操作。
class Expression:def interpret(self, context):passclass AmountExpression(Expression):def __init__(self, amount):self.amount = amountdef interpret(self, context):return context.get(self.amount)# 使用解释器模式
context = {"amount": 500}
expression = AmountExpression("amount")
print(expression.interpret(context))

注释

  • AmountExpression根据上下文解释并执行表达式。

16. 迭代器模式 (Iterator)
  • 解决的问题:需要在订单、购物车等集合对象中遍历商品。
  • 解决方法:通过迭代器模式,提供统一的接口来遍历集合中的商品,简化遍历操作。
class Cart:def __init__(self):self.items = []def add_item(self, item):self.items.append(item)def __iter__(self):return iter(self.items)# 使用迭代器模式
cart = Cart()
cart.add_item("Laptop")
cart.add_item("Phone")
for item in cart:print(item)

注释

  • Cart实现了迭代器模式,允许遍历购物车中的所有商品。

17. 中介者模式 (Mediator)
  • 解决的问题:多个系统组件(如订单管理、库存管理、支付系统)需要协调工作,但每个系统不应该直接依赖其他系统。
  • 解决方法:使用中介者模式,集中管理不同系统组件之间的通信和协调,避免紧耦合。
class Mediator:def process_payment(self, amount):passclass PaymentMediator(Mediator):def __init__(self, order, payment_processor):self.order = orderself.payment_processor = payment_processordef process_payment(self, amount):if self.order.is_valid():self.payment_processor.process_payment(amount)# 使用中介者模式
order = Order()
payment_processor = PaymentProcessor()
mediator = PaymentMediator(order, payment_processor)
mediator.process_payment(200)

注释

  • PaymentMediator协调订单和支付之间的交互。

18. 备忘录模式 (Memento)
  • 解决的问题:在处理订单时,需要记录订单的状态,以便进行回滚或恢复到某个历史状态(如订单变更前后的状态)。
  • 解决方法:使用备忘录模式保存对象的状态,允许在需要时恢复到之前的状态。
class Memento:def __init__(self, state):self.state = stateclass Originator:def __init__(self):self.state = ""def set_state(self, state):self.state = statedef save_state_to_memento(self):return Memento(self.state)def restore_state_from_memento(self, memento):self.state = memento.state# 使用备忘录模式
originator = Originator()
originator.set_state("Order created")
memento = originator.save_state_to_memento()
originator.set_state("Order paid")
originator.restore_state_from_memento(memento)

注释

  • Originator保存对象的状态,并能够恢复先前的状态。

19. 观察者模式 (Observer)
  • 解决的问题:订单状态发生变化时(例如,订单支付、发货等),需要通知相关的系统组件(如客户、库存系统等)。
  • 解决方法:通过观察者模式,当订单状态变化时,自动通知所有的观察者(如客户、仓库等)。
class Observer:def update(self, state):passclass OrderObserver(Observer):def update(self, state):print(f"Order state updated: {state}")class Order:def __init__(self):self.state = "Pending"self.observers = []def add_observer(self, observer):self.observers.append(observer)def set_state(self, state):self.state = stateself.notify()def notify(self):for observer in self.observers:observer.update(self.state)# 使用观察者模式
order = Order()
observer = OrderObserver()
order.add_observer(observer)
order.set_state("Paid")

注释

  • Order对象通知所有观察者当状态变化时进行更新。

20. 状态模式 (State)
  • 解决的问题:订单在生命周期中有多个状态(如待支付、已支付、已发货等),需要根据状态做不同的操作。
  • 解决方法:使用状态模式,管理订单的不同状态,每个状态对应不同的行为。
class OrderState:def handle(self, order):passclass PendingState(OrderState):def handle(self, order):print("Order is pending")class PaidState(OrderState):def handle(self, order):print("Order is paid")class Order:def __init__(self):self.state = PendingState()def set_state(self, state: OrderState):self.state = statedef process(self):self.state.handle(self)# 使用状态模式
order = Order()
order.process()  # Output: Order is pending
order.set_state(PaidState())
order.process()  # Output: Order is paid

注释

  • Order类的状态变化决定了其行为。

21. 策略模式 (Strategy)
  • 解决的问题:电商系统中有不同的支付方式(如信用卡、支付宝、微信支付),可以选择不同的支付策略来进行支付。
  • 解决方法:使用策略模式,封装不同的支付方式,客户可以根据需要选择不同的支付策略。
class PaymentStrategy:def pay(self, amount):passclass CreditCardStrategy(PaymentStrategy):def pay(self, amount):print(f"Paid {amount} with credit card")class PayPalStrategy(PaymentStrategy):def pay(self, amount):print(f"Paid {amount} with PayPal")class Order:def __init__(self, strategy: PaymentStrategy):self.strategy = strategydef process_payment(self, amount):self.strategy.pay(amount)# 使用策略模式
order = Order(CreditCardStrategy())
order.process_payment(100)

注释

  • PaymentStrategy定义了支付的不同策略,Order根据不同策略选择支付方式。

22. 模板方法模式 (Template Method)
  • 解决的问题:订单的处理流程大致相同,但在不同子类中可能有些许差异(如不同的验证方式、支付方式等)。
  • 解决方法:使用模板方法模式,定义一个固定的处理流程,具体步骤由子类实现。
class OrderProcessor:def process_order(self, order):self.verify_order(order)self.process_payment(order)self.ship_order(order)def verify_order(self, order):passdef process_payment(self, order):passdef ship_order(self, order):passclass OnlineOrderProcessor(OrderProcessor):def verify_order(self, order):print("Verifying online order")def process_payment(self, order):print("Processing online payment")def ship_order(self, order):print("Shipping online order")# 使用模板方法模式
processor = OnlineOrderProcessor()
processor.process_order("Order1")

注释

  • OrderProcessor定义了一个处理订单的框架,具体步骤由子类实现。

23. 访问者模式 (Visitor)
  • 解决的问题:电商系统中有多个不同类型的商品,而每种商品可能有不同的行为(例如折扣、税费计算等)。
  • 解决方法:使用访问者模式,允许在不改变商品类结构的情况下,新增商品行为(如计算税费、折扣等)。
class Cart:def __init__(self):self.items = []def add_item(self, item):self.items.append(item)def accept(self, visitor):for item in self.items:visitor.visit(item)class CartVisitor:def visit(self, item):passclass TaxVisitor(CartVisitor):def visit(self, item):print(f"Calculating tax for {item}")# 使用访问者模式
cart = Cart()
cart.add_item("Laptop")
cart.accept(TaxVisitor())

注释

  • CartVisitor用于对购物车中的商品执行操作(如计算税费)。

总结:

在电商系统中,通过这些设计模式的应用,我们可以有效地解耦系统各个组件,确保代码的灵活性、扩展性和可维护性。每种设计模式都有其独特的作用,帮助我们应对各种复杂的业务需求和变化。
当然可以!下面我将对每一段代码进行逐行注释,帮助你更清楚地理解每个设计模式的应用。

相关文章:

一个电商场景串联23种设计模式:创建型、结构型和行为型

理解了&#xff01;你希望有一个具体的项目案例&#xff0c;能够涵盖所有23种设计模式&#xff0c;并且将它们分类为创建型、结构型和行为型。这个需求非常好&#xff0c;能够帮助你从实际的应用场景理解每种设计模式的用法。 为了实现这个目标&#xff0c;我将为你设计一个电…...

浅拷贝和深拷贝的区别

Person p1 new Person(10);Person p2 p1;p2.age 20;System.out.println(p1p2); // trueSystem.out.println(p1.age); // 20 这种做法只是复制了对象的地址&#xff0c;即两个变量现在是指向了同一个对象&#xff0c;任意一个变量&#xff0c;操作了对象的属性&#xff0c;都…...

Java开发者面试实录:微服务架构与Spring Cloud的应用

面试场景 面试官: 请介绍一下你的基本情况。 程序员: 大家好&#xff0c;我叫张小明&#xff0c;今年27岁&#xff0c;硕士学历&#xff0c;拥有5年的Java后端开发经验。主要负责基于Spring Boot开发企业级应用&#xff0c;以及微服务架构的设计和实现。 面试官: 好的&#…...

在Ubuntu系统中安装桌面环境

在 Ubuntu 系统中安装桌面环境可以通过包管理器 apt 或工具 tasksel 实现。以下是详细的安装方法和常见桌面环境的选择&#xff1a; --- ### **1. 准备系统更新** 在安装前&#xff0c;建议更新软件源和系统包&#xff1a; bash sudo apt update && sudo apt upgrade…...

多语言笔记系列:Polyglot Notebooks 中使用 xUnit 单元测试

Polyglot Notebooks 中使用 xUnit 单元测试 本文目录 Polyglot Notebooks 中使用 xUnit 单元测试[TOC](本文目录)Polgylot Notebooks 并没有直接支持单元测试框架。不能像VS里那样方便的进行单元测试。简单远行的话&#xff0c;可以使用下面的方案&#xff01;1、引入必要的NuG…...

Cisco Packet Tracer 选项卡的使用

目录 设备Config选项卡的使用 Realtime and Simulation模式&#xff08;数据包跟踪与分析&#xff09; 设备Desktop选项卡的使用 设备Config选项卡的使用 Hostname NVRAM Startup Config----Load 加载 INTERFACE 点击on Save 如果&#xff0c;不把Running Config保存为Sta…...

杨校老师竞赛课之C++备战蓝桥杯初级组省赛

目录 1. 灯塔 题目描述 输入描述 输出描述 输入样例1 输出样例1 输入样例2 输出样例2 数据说明 2. 子区间 题目描述 输入描述 输出描述 输入样例 输出样例 数据说明 3. 染色 题目描述 输入描述 输出描述 输入样例1 输出样例1 输入样例2 输出样例2 数据…...

gcc/g++用法摘记

链接静态库 gcc main.o -L/path/to/libs -lmylib -o myprogram 【待续】...

kotlin 扩展函数

Kotlin 扩展函数的定义与使用 定义扩展函数 Kotlin 的扩展函数是一种强大的机制&#xff0c;允许开发者为已有的类添加额外的功能&#xff0c;而无需继承该类或对其进行任何修改。这种特性极大地提高了代码的灵活性和可读性。 扩展函数可以通过在函数名称前指定目标类型的接…...

机器人强化学习入门学习笔记

(1)物理引擎 物理引擎就是模拟真实世界物理规律的软件工具。它会根据你给定的物体、质量、形状、力等信息,计算这些物体在时间上的运动和相互作用。如果你设计了一个机器人,那物理引擎就是“虚拟现实世界”,让机器人在里面“活起来”,模拟它走路、抓东西、摔倒等动作。而…...

《RESTful API版本控制的哲学思辨:稳定性与创新性的终极平衡》

有效的版本控制&#xff0c;就如同精密仪器中的校准装置&#xff0c;确保API在不断升级的过程中&#xff0c;依然能与旧有系统无缝对接&#xff0c;维持整个生态的平稳运行。 不同的客户端对API的依赖程度和使用方式各不相同。有些客户端可能因为各种原因&#xff0c;无法及时…...

spring中spring-boot-configuration-processor的使用

spring-boot-configuration-processor 是 Spring Boot 提供的注解处理器&#xff0c;用于在编译阶段生成配置元数据文件&#xff08;spring-configuration-metadata.json&#xff09;&#xff0c;从而优化开发体验。以下是其核心功能和使用指南&#xff1a; 一、核心功能 IDE 智…...

30天开发操作系统 第27天 -- LDT与库

前言 大家早上好&#xff0c;我们今天的第一个任务就是修复昨天晚上的那个bug。是个什么bug来着&#xff1f;就是用nsct命令运行的应用程序&#xff0c;无论是按ShiftF1还是点击窗口的“x”按钮都没有反应的那个bug啦。 我们得先来找到出问题的原因&#xff0c;然后才能采取对…...

std::move()详解

一、std::move()的作用和原理 本质&#xff1a; std::move()并不像字面意思“搬走”那些对象&#xff0c;而是&#xff1a; 将传入的对象“强制转化”为右值引用类型&#xff0c;从而开启“移动语义”。 在源码层面&#xff1a; 复制代码 template<typename T> std::…...

linux系统基本操作命令

文件和目录操作 ls&#xff1a;列出目录内容。 例如&#xff1a;ls -l 显示详细信息&#xff0c;ls -a 显示包括隐藏文件在内的所有文件。 cd&#xff1a;改变当前目录。 例如&#xff1a;cd /home/username 切换到指定目录。 pwd&#xff1a;显示当前目录的完整路径。 mk…...

python打卡day16

NumPy 数组基础 因为前天说了shap&#xff0c;这里涉及到数据形状尺寸问题&#xff0c;所以需要在这一节说清楚&#xff0c;后续的神经网络我们将要和他天天打交道。 知识点&#xff1a; numpy数组的创建&#xff1a;简单创建、随机创建、遍历、运算numpy数组的索引&#xff1a…...

架构进阶:什么是数据架构,如何理解数据架构?(华为)

数据架构是企业架构的重要组成部分,DAMA、IBM 及国内大厂对其定义各有侧重。它包含数据资产目录、数据标准、数据模型和数据分布四个组件。数据资产目录可梳理企业数据资产,数据标准统一数据含义和规则,数据模型反映业务对象关联关系,数据分布呈现数据流动情况。数据架构是…...

基于EFISH-SCB-RK3576工控机/SAIL-RK3576核心板的KTV点歌主机技术方案‌(国产化替代J1900的全场景技术解析)

‌一、硬件架构设计‌ ‌多媒体处理模块‌ ‌超高清解码‌&#xff1a; RK3576 NPUGPU协同解码&#xff0c;支持4K60fps H.265硬解&#xff08;功耗<5W&#xff09;&#xff0c;支持8路1080P视频同步预览对比J1900需外接VPU解码芯片&#xff0c;硬件成本降低40%&#xff0c;…...

Java面试深度解密:Spring Boot、Redis、日志优化、JUnit5及Kafka事务核心技术解析

模拟面试实战 面试官&#xff1a;请解释Spring Boot的自动配置原理&#xff1f;哪些关键注解参与了这一过程&#xff1f; xbhog&#xff1a;Spring Boot通过AutoConfiguration标记核心配置类&#xff0c;通过ConditonalOnClass和ConditionalOnMissingBean判断依赖是否存在并自…...

内存碎片深度剖析

目录 什么是内存碎片 内部碎片的解决 malloc STL二级空间配置器 外部碎片的解决 伙伴系统算法 slab分配器 什么是内存碎片 内存碎片是指在内存中存在的一些不连续的、较小的空闲内存块&#xff0c;这些小块内存由于太小而无法被有效地分配给程序使用&#xff0c;从而导…...

飞帆网页中使用 i 评论插件

https://fvi.cn/786...

DeepSeek成本控制的三重奏

知识蒸馏 使用规则引擎筛选合成数据&#xff0c;来替代90%的人工标注 动态精度切换&#xff1a;“节能模式” 根据任务复杂度自动切换FP16/INT8精度&#xff0c;单位token能耗低至0.0028瓦时&#xff0c;推理电费成本降低82% 极致压缩训练 通过以上的技术&#xff0c;降低训练…...

五一の自言自语 2025/5/5

今天开学了&#xff0c;感觉还没玩够。 假期做了很多事&#xff0c;弄了好几天的路由器、监控、录像机&#xff0c;然后不停的出现问题&#xff0c;然后问ai&#xff0c;然后解决问题。这次假期的实践&#xff0c;更像是计算机网络的实验&#xff0c;把那些交换机&#xff0c;…...

效整理文件信息!一键生成文件夹目录的工具

一、软件介绍 大家好&#xff0c;今天给大家推荐一款实用的文件夹目录生成工具&#xff0c;它能快速提取文件夹内的文件信息&#xff0c;并整理成Excel表格&#xff0c;包含文件名、路径、类型、创建/修改时间、大小等关键数据。 为什么需要这个工具&#xff1f; 之前我想整理…...

关闭ollama开机自启动

不同操作系统关闭Ollama开机自启动的方法有所不同&#xff0c;以下是常见操作系统的具体方法&#xff1a; Windows系统 通过任务管理器&#xff1a;按Ctrl Shift Esc打开任务管理器&#xff0c;切换到“启动”选项卡&#xff0c;在列表中找到Ollama&#xff08;或相关条目&a…...

2025 年最新树莓派 Pico 连接 ESP8266 模块实现 WiFi 通信、搭建 TCP 服务器实现数据交互详细教程

AT 指令基本结构概述 AT 指令最初由 Hayes 公司为其调制解调器&#xff08;modem&#xff09;开发&#xff0c;目的是提供一种标准化的方式来控制通信设备。最早的 Hayes Smartmodem 300 调制解调器&#xff08;1981年&#xff09;引入了这一指令集&#xff0c;因此 AT 指令也…...

java类=null的回收

在Java&#xff08;或类似使用垃圾回收的语言&#xff09;中&#xff0c;当你执行 a null 后&#xff0c;对象 B() 是否会被回收取决于是否还有其他引用指向它。具体分析如下&#xff1a; 关键点&#xff1a; 引用链分析&#xff1a; 初始时&#xff1a;a 引用了 A 实例&#…...

2025系统架构师---论面向对象的软件设计

摘要 自“软件危机”出现过后&#xff0c;工程化软件开发方法不断发展&#xff0c;采用什么方法对大 规模软件进行设计并保证软件的质量。在这样背景下&#xff0c;人们开始从面向数据流过 程开发法中不断思考&#xff0c;进而引入对象的概念。对象是数据与行为的封装&#…...

如何判断node节点是否启用cgroup?

要判断 Linux 节点是否启用了 cgroup&#xff08;Control Groups&#xff09;&#xff0c;可以通过以下方法验证&#xff1a; 方法 1&#xff1a;检查 /proc/cgroups 文件 查看内核支持的 cgroup 子系统列表&#xff1a; cat /proc/cgroups 输出说明&#xff1a; 若文件不存…...

学习黑客Nmap 实战

金丹期第三重 — Debian 12 实战&#xff1a;Nmap 全流程探秘 testhtml5.vulnweb.com 晋阶宣言 本章彻底补完前面“只扫到 80/443 却没识别 nginx 版本”的缺憾。 道友将依次完成 快速侦查 → 深度洞察 → NSE 弱点扫描 三连招&#xff0c;并学会用 -sV、-Pn、--script-trace 等…...

AD创建元件符号

在创建好工程文档之后打开SCH Library 创建工程的方法&#xff1a;AD创建一个工程文档-CSDN博客 这里以创建一个电容符号为例子&#xff0c;先创建引脚&#xff0c;画引脚的时候要把网格尺寸设置为100mil AD原理图怎么改网格尺寸-CSDN博客 放置好引脚之后绘制元素&#xff0…...

第六章:6.1 ESP32教学:多任务处理与FreeRTOS实战

一、FreeRTOS简介 ESP32内置了FreeRTOS实时操作系统内核&#xff0c;这是一个专为嵌入式系统设计的开源实时操作系统。它支持&#xff1a; 多任务并行处理 任务优先级管理 内存管理 任务间通信 定时器管理 二、任务创建与管理 1. 任务创建&#xff08;xTaskCreate&…...

Python生活手册-正则表达式:从快递单到咖啡订单的文本魔法

一、快递单号识别术&#xff08;基础匹配&#xff09; 1. 数字猎人&#xff08;\d&#xff09; 想象你有一叠快递单需要自动识别&#xff1a; import re快递单 "【顺丰】单号&#xff1a;SF123456789 签收人&#xff1a;张先生" 单号 re.search(r"SF\d&quo…...

Windows 自带删除缓存

Temp临时文件文件夹手动除 Windows键R 快速打开运行输入%temp%,其下所有文件删除 打开储存感知 打开「设置」→「系统」→「存储」&#xff0c;点击右侧面板中的「配置存储感知或立即运行」。将弹出页拉至最下方&#xff0c;勾选其中的「删除以前版本的 Windows」&#xff0c;再…...

Linux电源管理(6)_Generic PM之挂起功能

原文链接&#xff1a;Linux电源管理&#xff08;6&#xff09;_Generic PM之挂起功能 1.前言 Linux内核提供了三种暂停方式&#xff1a;Freeze&#xff0c;Standby和STR&#xff08;暂停到RAM&#xff09;&#xff0c;在用户空间向” / sys / power / state”文件分别写入“ …...

MCP原理详解及实战案例(动嘴出UI稿、3D建模)

文章目录 MCP 原理介绍架构核心组件协议层传输层连接生命周期MCP与function calling: 互补关系 MCP python SDKMCP的优点 怎么用MCP&#xff1a;天气服务参考应用项目&#xff1a; REF 24年11月份&#xff0c;claude推出了模型上下文协议( MCP),作为一种潜在的解决方案&#xf…...

【Java项目脚手架系列】第二篇:JavaWeb项目脚手架

【Java项目脚手架系列】第二篇&#xff1a;JavaWeb项目脚手架 前言 在Java Web开发中&#xff0c;一个好的项目脚手架可以大大提高开发效率&#xff0c;减少重复工作。本篇文章将介绍一个基于Maven的JavaWeb项目脚手架&#xff0c;它包含了基础的Web开发配置和常用功能。 什…...

【机器学习-线性回归-5】多元线性回归:概念、原理与实现详解

线性回归是机器学习中最基础且广泛应用的算法之一&#xff0c;而多元线性回归则是其重要扩展。本文将全面介绍多元线性回归的核心概念、数学原理及多种实现方式&#xff0c;帮助读者深入理解这一强大的预测工具。 1. 多元线性回归概述 1.1 什么是多元线性回归 多元线性回归(…...

《TCP/IP详解 卷1:协议》之第十章:动态选路协议

目录 一、常见的动态路由协议 二、RIP 1、RIP 版本1&#xff1a; 1.1、报文格式 2、RIP 版本2&#xff1a; 2.1、报文格式 三、OSPF 1、链路状态路由协议 2、工作原理 3、OSPF的特点 四、BGP 五、参考链接 一、常见的动态路由协议 路由协议&#xff08;Routing Pr…...

逆向常见题目—迷宫类题目

逆向常见题目—迷宫类题目 迷宫(maze) 思路&#xff1a; 1.找到地图(字符串) 2.找到方向(上左下右) 3.找到起点到终点 然后将路径输出即可 特征: 标题,hint为maze 或者 看到字符串###等等 整理字符串为图形.py (要是不是正方形需要自己输出行和列) import mathdef arra…...

Redis 数据类型详解(二):Hash 类型全解析

文章目录 一、什么是 Redis 的 Hash 类型&#xff1f;二、Hash为什么在有些时候比String好用三、常见命令1.HSET key field value2.HGET key field3.HMSET4.HMGET5.HGETALL6.HKEYS7.HVALS8.HINCRBY9.HSETNX 四、应用场景五、性能优势六、注意事项总结 提示&#xff1a;以下是本…...

Vite简单介绍

Vite 是一个现代化的前端构建工具&#xff0c;由 Vue.js 的创始人 Evan You 开发&#xff0c;旨在提供更快的开发体验和更高效的构建流程。它的名字来源于法语单词“vite”&#xff0c;意为“快速”&#xff0c;这也反映了它的核心优势——极速的冷启动和热模块替换&#xff08…...

jwt身份验证和基本的利用方式

前言 &#xff1a; 什么是jwt&#xff08;json web token&#xff09;&#xff1f; 看看英文单词的意思就是 json形式的token 他的基本的特征 &#xff1a; 类似于这样的 他有2个点 分割 解码的时候会有三个部分 头部 payload 对称密钥 这个就是对称加密 头部&am…...

基于YOLOv的目标检测训练数据构建方法研究—图像采集、标注、划分与增强一体化流程设计

在目标检测任务中&#xff0c;高质量的训练数据是模型性能提升的关键。本文围绕 YOLOv 系列模型&#xff0c;系统性地研究了目标检测训练数据的构建方法&#xff0c;提出了一套从图像采集、标注、数据集划分到数据增强的一体化流程设计 。通过多源图像采集策略确保样本多样性&a…...

c++类【开端】

运算符重载 方式&#xff1a;operator运算符(参数列表&#xff09;{}。 运算符就是&#xff1a;-*/[]等。 运算符重载&#xff0c;和定义一个方法效果是一样的&#xff0c;只是&#xff0c;重载运算符让类的-*/等操作看起来和普通数字的-*/一样。仅是看起来一样。我们重载运算符…...

wordperss AI插件:AI图文+视频+长尾关键词自动生成,已内置deepseek、kimi全模型,支持简单一键接入更多自定义API

【2.17最新版】Linkreate wordperss AI插件&#xff1a;AI图文视频长尾关键词自动生成&#xff0c;已内置deepseek、kimi全模型。 支持自定义接入其它API&#xff0c;包括但不限于腾讯云API和它的deepseek模型 后台只需要设置对应的API url 、模型 、API key,就可以让插件调用…...

【免费分享无广告】刷视频助手抖音快手小红书视频号自动脚本刷视频养号

养号可做极速版刷视频任务支持最新版软件 【资 源 名 称】刷视频助手 【资 源 版 本】1.0.2 【资 源 大 小】11.66M 【资 源 系 统】安卓 【资 源 介 绍】刷视频养号助手&#xff0c;操作简单&#xff0c;就一个页面。亲测无广纯净&#xff0c;打开即用 ———————————…...

Javascript大致框架

一、JavaScript简介 JavaScript&#xff0c;简称JS&#xff0c;是一种高级的、解释型的编程语言&#xff0c;主要用于为网页添加动态功能。它最初由Netscape公司于1995年推出&#xff0c;最早名为LiveScript&#xff0c;后更名为JavaScript。尽管名字中带有“Java”&#xff0…...

Linux 权限

目录 一、Linux 权限概念 1.1 用户 1.2 用户切换 1.3 sudo指令提权 1.4 文件访问者的分类&#xff08;人&#xff09; 1.5 文件类型和访问权限&#xff08;事物属性&#xff09; 1.6 文件访问权限和相关设置方法 1&#xff09; chmod 2&#xff09;chown 3)chgrp 二…...

linux stm32mp157 GIC-V2 中断处理过程分析

/* ** 中断触发时&#xff0c;调用的 handle_arch_irq 入口地址。 ** 因为此时&#xff0c;挂接的就是 gic_handle_irq 函数&#xff01;gic_handle_irq 是个全局函数指针&#xff0c; ** static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ** 它是Lin…...