设计模式之一场景贯穿

使用一个场景化的需求来连贯 22 种设计模式来记忆,
假设需求是搭建一个电商服务器(后端),我们从用户浏览商品、下单、支付到售后等流程(如果流程不全面再加上去),贯穿所有设计模式
设计模式的中文名分别说明,起好设计模式会用到的英文类名和对应的函数名来解释。

需求:搭建电商平台后端,涉及用户浏览、下单、支付、售后等完整流程


创建型模式

  1. 工厂方法(Factory Method)

    类名:UserAccountFactory
    函数名:createUserAccount()
    场景:在用户注册时,根据用户身份(如 Customer​、Seller​、Admin​)创建相应的账户类型。
    原因:用户注册时,不同身份(如 Customer​、Seller​、Admin​)需要不同的功能和权限。工厂方法模式可以根据身份创建特定的账户对象,确保灵活性和扩展性。

    工厂方法-go1

  2. 抽象工厂(Abstract Factory)

    类名:ServiceFactory
    函数名:createAuthService()​、createPaymentService()
    场景:针对不同平台(如国内和国际),提供特定的服务套件,如支付和身份验证模块的实现。
    原因:电商平台需兼容国内外不同支付和认证系统。抽象工厂模式提供一套适应不同平台的服务对象创建方案,使代码可以灵活切换环境而不影响整体结构。

    抽象工厂-go2

  3. 生成器(Builder)

    类名:OrderBuilder
    函数名:addProduct()​、setDeliveryAddress()​、setPaymentMethod()
    场景:在用户下单时,逐步构建订单对象,将商品、配送地址和支付方式组合到订单中。
    原因:下单过程需要逐步构建订单,如添加商品、设置配送地址和支付方式。生成器模式能够按步骤创建复杂的对象,确保订单构建的顺序和结构。

    生成器-go3

  4. 原型(Prototype)

    类名:ProductPrototype
    函数名:clone()
    场景:针对用户购物车中的商品,复制某个已有商品对象,通过克隆快速生成相同商品实例。
    原因:为满足用户快速添加多个相同商品至购物车的需求,原型模式可以通过克隆已有商品对象,避免每次重新创建,节省时间和系统资源。

    原型-go4

  5. 单例(Singleton)

    类名:CartService
    函数名:getInstance()
    场景:每个用户在整个浏览会话中共享唯一的购物车实例,用于管理当前添加的商品。
    原因:每个用户在会话中应使用唯一的购物车实例。单例模式确保每个用户的购物车只有一个实例,避免数据不一致并节省系统资源。

    单例-go5


结构型模式

  1. 适配器(Adapter)

    类名:PaymentGatewayAdapter
    函数名:processPayment()
    场景:将不同支付网关(如 PayPal​、Stripe​)接口适配到统一支付处理接口。
    原因:不同支付网关接口(如 PayPal​、Stripe​)可能有各自的 API。适配器模式将这些接口适配为统一的支付处理接口,方便调用和扩展。

    适配器-go6

  2. 桥接(Bridge)

    类名:ProductInfo​ 和 DisplayPlatform
    函数名:showDetails()
    场景:为商品展示在不同平台(如 Web 端、移动端)提供不同的展示结构,桥接商品信息和展示平台。
    原因:商品信息展示在 Web 和移动端的布局和格式不同。桥接模式将商品信息和展示平台分离,便于灵活调整展示方式。

    桥接-go7

  3. 组合(Composite)

    类名:Category
    函数名:addSubCategory()​、displayProducts()
    场景:实现商品分类树状结构,方便电商平台展示不同级别的商品分类及子分类。
    原因:商品分类和子分类形成树状结构,组合模式使得树形结构中父类和子类具有一致性,便于递归显示和操作不同层级的分类。

    组合-go8

  4. 装饰(Decorator)

    类名:ProductDecorator
    函数名:getDescription()
    场景:在商品详情页,为商品动态添加如促销、折扣等信息装饰,实现多样化的商品描述。
    原因:在商品详情页,需要动态添加促销、折扣等装饰信息。装饰模式允许在不改变基础商品对象的情况下,灵活地添加额外信息。

    装饰-go9

  5. 外观(Facade)

    类名:OrderFacade
    函数名:processOrder()
    场景:用户下单时,通过外观模式一次性调用支付、库存、配送等模块,简化后端订单处理流程。
    原因:下单流程涉及多个系统模块(如支付、库存、物流等)的调用,外观模式通过统一接口封装复杂的内部调用逻辑,简化客户端操作。

    外观-go10

  6. 享元(Flyweight)

    类名:ProductImageFlyweight
    函数名:getImage()
    场景:使用享元模式共享重复商品的图片资源,避免内存浪费。
    原因:同一商品的图片资源会在页面多次使用,享元模式可以共享相同图片对象,节省内存,提升系统性能。

    享元-go11

  7. 代理(Proxy)

    类名:OrderProxy
    函数名:processOrder()
    场景:代理控制用户的订单操作权限,比如顾客只能查看订单状态,管理员可以取消订单。
    原因:在订单系统中,不同用户权限对订单有不同的操作需求。代理模式可以在用户和订单系统之间控制访问权限,保障数据安全。

    代理-go12


行为模式

  1. 责任链(Chain of Responsibility)

    类名:OrderHandlerChain
    函数名:handle()
    场景:订单处理流程中,依次经过库存检查、支付确认、配送等多个步骤进行处理。
    原因:订单处理需要多个步骤依次完成,如库存检查、支付确认等。责任链模式能够灵活调整和扩展处理步骤。

    责任链-go13

  2. 命令(Command)

    类名:CartCommand
    函数名:execute()​、undo()
    场景:用户的购物车操作(如添加商品、移除商品)使用命令模式记录,以便可以撤销或重做操作。
    原因:用户对购物车的操作(如添加、移除商品)可以用命令模式记录,便于实现撤销、重做等功能,提升用户体验。

    命令-go14

  3. 迭代器(Iterator)

    类名:ProductIterator
    函数名:next()​、hasNext()
    场景:在浏览商品列表或分页查看时,通过迭代器模式简化商品迭代的处理。
    原因:用户浏览商品列表时,迭代器模式为分页提供统一的迭代接口,简化遍历操作,提高代码的灵活性和扩展性。

    迭代器-go15

  4. 中介者(Mediator)

    类名:CheckoutMediator
    函数名:notify()
    场景:在订单结算过程中,不同模块(如支付、库存、物流)通过中介者模式协同工作,避免模块间直接耦合。
    原因:在订单结算过程中,支付、库存、物流等模块间相互通信复杂。中介者模式通过协调模块间交互,减少耦合,便于维护和扩展。

    中介者-go16

  5. 备忘录(Memento)

    类名:OrderStateMemento
    函数名:save()​、restore()
    场景:在用户修改订单前保存当前状态,以便在用户回退或恢复至之前状态时使用。
    原因:用户在修改订单前保存状态,用备忘录模式可以保存和恢复订单状态,确保用户在回退时获得正确数据。

    备忘录-go17

  6. 观察者(Observer)

    类名:OrderStatusObserver
    函数名:update()
    场景:当订单状态变化(如发货、送达)时,通知用户和物流系统状态更新。
    原因:当订单状态变化(如发货、送达)时,观察者模式可以将状态更新通知用户和物流系统,保证信息实时同步。

    观察者-go18

  7. 状态(State)

    类名:OrderState
    函数名:nextState()
    场景:订单的不同状态(如已下单、已发货、已收货、完成)通过状态模式管理转移逻辑。
    原因:订单在不同状态间转换时,使用状态模式可以封装状态转移逻辑,简化状态管理,确保状态变化符合业务规则。

    状态-go19

  8. 策略(Strategy)

    类名:DiscountStrategy
    函数名:applyDiscount()
    场景:在商品折扣计算中,针对不同优惠策略(如满减、折扣、赠品)使用策略模式动态选择。
    原因:商品折扣可以有多种策略(如满减、折扣、赠品),策略模式通过封装算法实现动态选择不同的优惠策略。

    策略-go20

  9. 模板方法(Template Method)

    类名:OrderProcessingTemplate
    函数名:process()
    场景:定义订单处理的模板方法,不同类型订单(如虚拟商品、实物商品)可以复用通用流程,并在特定步骤自定义。
    原因:订单处理步骤可以复用一部分逻辑,不同订单类型的特定流程可以在模板方法中自定义,确保通用流程的可维护性。

    模板方法-go21

  10. 访问者(Visitor)

    类名:ReportVisitor
    函数名:visitOrder()​、visitCustomer()
    场景:为生成数据报表,访问订单、客户信息等结构化数据,执行不同统计分析逻辑。
    原因:报表生成需要对订单和客户信息进行不同的数据统计分析,访问者模式能为不同结构化数据提供特定访问逻辑,便于扩展统计类型。

    访问者-go22


  1. 工厂方法-go

    下面是使用 Go 实现的一个工厂方法模式示例代码,通过 UserAccountFactory​ 创建不同的用户账户类型(如 Customer​、Seller​、Admin​)。

    package main
    
    import "fmt"
    
    // UserAccount 定义用户账户接口
    type UserAccount interface {
    	GetRole() string
    }
    
    // Customer 定义顾客账户
    type Customer struct{}
    
    func (c *Customer) GetRole() string {
    	return "Customer"
    }
    
    // Seller 定义卖家账户
    type Seller struct{}
    
    func (s *Seller) GetRole() string {
    	return "Seller"
    }
    
    // Admin 定义管理员账户
    type Admin struct{}
    
    func (a *Admin) GetRole() string {
    	return "Admin"
    }
    
    // UserAccountFactory 创建用户账户的工厂方法
    func UserAccountFactory(accountType string) UserAccount {
    	switch accountType {
    	case "Customer":
    		return &Customer{}
    	case "Seller":
    		return &Seller{}
    	case "Admin":
    		return &Admin{}
    	default:
    		return nil
    	}
    }
    
    func main() {
    	// 使用工厂方法创建不同用户账户
    	customer := UserAccountFactory("Customer")
    	seller := UserAccountFactory("Seller")
    	admin := UserAccountFactory("Admin")
    
    	fmt.Println("Created account type:", customer.GetRole())
    	fmt.Println("Created account type:", seller.GetRole())
    	fmt.Println("Created account type:", admin.GetRole())
    }
    

    代码解释

    1. UserAccount​ 接口定义了一个通用方法 GetRole​,表示不同类型账户的角色。
    2. Customer​、Seller​ 和 Admin​ 是不同的账户类型,实现了 UserAccount​ 接口。
    3. UserAccountFactory​ 是工厂方法,根据传入的 accountType​ 返回对应账户类型的实例。
    4. main​ 函数中,通过调用 UserAccountFactory​ 创建不同的账户类型,并输出它们的角色类型。

    输出结果

    Created account type: Customer
    Created account type: Seller
    Created account type: Admin
    
  2. 抽象工厂-go

    下面是使用 Go 实现的一个抽象工厂模式示例代码。ServiceFactory​ 用于创建不同平台(如 DomesticServiceFactory​ 和 InternationalServiceFactory​)的支付和身份验证服务。

    package main
    
    import "fmt"
    
    // AuthService 定义身份验证服务接口
    type AuthService interface {
    	Authenticate() string
    }
    
    // PaymentService 定义支付服务接口
    type PaymentService interface {
    	ProcessPayment() string
    }
    
    // DomesticAuthService 国内身份验证服务实现
    type DomesticAuthService struct{}
    
    func (d *DomesticAuthService) Authenticate() string {
    	return "国内身份验证成功"
    }
    
    // InternationalAuthService 国际身份验证服务实现
    type InternationalAuthService struct{}
    
    func (i *InternationalAuthService) Authenticate() string {
    	return "国际身份验证成功"
    }
    
    // DomesticPaymentService 国内支付服务实现
    type DomesticPaymentService struct{}
    
    func (d *DomesticPaymentService) ProcessPayment() string {
    	return "国内支付成功"
    }
    
    // InternationalPaymentService 国际支付服务实现
    type InternationalPaymentService struct{}
    
    func (i *InternationalPaymentService) ProcessPayment() string {
    	return "国际支付成功"
    }
    
    // ServiceFactory 抽象工厂接口
    type ServiceFactory interface {
    	CreateAuthService() AuthService
    	CreatePaymentService() PaymentService
    }
    
    // DomesticServiceFactory 国内服务工厂
    type DomesticServiceFactory struct{}
    
    func (d *DomesticServiceFactory) CreateAuthService() AuthService {
    	return &DomesticAuthService{}
    }
    
    func (d *DomesticServiceFactory) CreatePaymentService() PaymentService {
    	return &DomesticPaymentService{}
    }
    
    // InternationalServiceFactory 国际服务工厂
    type InternationalServiceFactory struct{}
    
    func (i *InternationalServiceFactory) CreateAuthService() AuthService {
    	return &InternationalAuthService{}
    }
    
    func (i *InternationalServiceFactory) CreatePaymentService() PaymentService {
    	return &InternationalPaymentService{}
    }
    
    func main() {
    	// 创建国内服务工厂
    	var domesticFactory ServiceFactory = &DomesticServiceFactory{}
    	authService := domesticFactory.CreateAuthService()
    	paymentService := domesticFactory.CreatePaymentService()
    	fmt.Println(authService.Authenticate())
    	fmt.Println(paymentService.ProcessPayment())
    
    	// 创建国际服务工厂
    	var internationalFactory ServiceFactory = &InternationalServiceFactory{}
    	authService = internationalFactory.CreateAuthService()
    	paymentService = internationalFactory.CreatePaymentService()
    	fmt.Println(authService.Authenticate())
    	fmt.Println(paymentService.ProcessPayment())
    }
    

    代码解释

    1. 接口定义AuthService​ 和 PaymentService​ 分别定义身份验证和支付的接口。
    2. 实现具体服务DomesticAuthService​ 和 InternationalAuthService​ 实现身份验证服务,DomesticPaymentService​ 和 InternationalPaymentService​ 实现支付服务。
    3. 抽象工厂ServiceFactory​ 接口定义创建身份验证和支付服务的抽象方法。
    4. 具体工厂实现DomesticServiceFactory​ 和 InternationalServiceFactory​ 分别实现了国内和国际服务工厂。
    5. 主函数调用:在 main​ 函数中,通过工厂实例化了不同平台的身份验证和支付服务。

    输出结果

    国内身份验证成功
    国内支付成功
    国际身份验证成功
    国际支付成功
    
  3. 生成器-go

    下面是使用 Go 实现的一个生成器模式示例代码,通过 OrderBuilder​ 来逐步构建订单对象(Order​),包括添加商品、设置配送地址和支付方式。

    package main
    
    import "fmt"
    
    // Order 订单对象
    type Order struct {
    	Products        []string
    	DeliveryAddress string
    	PaymentMethod   string
    }
    
    // OrderBuilder 定义订单生成器
    type OrderBuilder struct {
    	order *Order
    }
    
    // NewOrderBuilder 创建一个新的订单生成器
    func NewOrderBuilder() *OrderBuilder {
    	return &OrderBuilder{&Order{}}
    }
    
    // AddProduct 添加商品到订单
    func (b *OrderBuilder) AddProduct(product string) *OrderBuilder {
    	b.order.Products = append(b.order.Products, product)
    	return b
    }
    
    // SetDeliveryAddress 设置订单配送地址
    func (b *OrderBuilder) SetDeliveryAddress(address string) *OrderBuilder {
    	b.order.DeliveryAddress = address
    	return b
    }
    
    // SetPaymentMethod 设置订单支付方式
    func (b *OrderBuilder) SetPaymentMethod(method string) *OrderBuilder {
    	b.order.PaymentMethod = method
    	return b
    }
    
    // Build 构建最终的订单
    func (b *OrderBuilder) Build() *Order {
    	return b.order
    }
    
    func main() {
    	// 使用生成器模式逐步构建订单
    	order := NewOrderBuilder().
    		AddProduct("Laptop").
    		AddProduct("Phone").
    		SetDeliveryAddress("123 Main St, Springfield").
    		SetPaymentMethod("Credit Card").
    		Build()
    
    	fmt.Printf("Order Details:\nProducts: %v\nDelivery Address: %s\nPayment Method: %s\n",
    		order.Products, order.DeliveryAddress, order.PaymentMethod)
    }
    

    代码解释

    1. Order:表示订单对象,包含商品列表、配送地址和支付方式。
    2. OrderBuilder:生成器类,用于逐步构建 Order​ 对象,通过链式方法 AddProduct​、SetDeliveryAddress​ 和 SetPaymentMethod​ 设置订单信息。
    3. NewOrderBuilder:创建并初始化一个新的 OrderBuilder​ 实例。
    4. Build:返回最终构建的 Order​ 对象。
    5. 主函数调用:在 main​ 函数中,调用 OrderBuilder​ 逐步添加商品、设置地址和支付方式,最后生成订单。

    输出结果

    Order Details:
    Products: [Laptop Phone]
    Delivery Address: 123 Main St, Springfield
    Payment Method: Credit Card
    
  4. 原型-go

    以下是使用 Go 实现的原型模式示例代码,通过 ProductPrototype​ 接口来克隆商品对象,方便在购物车中快速复制已有的商品。

    package main
    
    import "fmt"
    
    // ProductPrototype 定义克隆方法的接口
    type ProductPrototype interface {
    	Clone() ProductPrototype
    	GetInfo() string
    }
    
    // Product 商品结构体
    type Product struct {
    	Name  string
    	Price float64
    }
    
    // Clone 实现 ProductPrototype 接口中的 Clone 方法
    func (p *Product) Clone() ProductPrototype {
    	// 创建一个新的 Product 实例,复制当前对象的值
    	return &Product{
    		Name:  p.Name,
    		Price: p.Price,
    	}
    }
    
    // GetInfo 获取商品信息
    func (p *Product) GetInfo() string {
    	return fmt.Sprintf("Product Name: %s, Price: %.2f", p.Name, p.Price)
    }
    
    func main() {
    	// 创建一个商品原型
    	originalProduct := &Product{
    		Name:  "Laptop",
    		Price: 1500.00,
    	}
    
    	// 克隆商品
    	clonedProduct := originalProduct.Clone()
    
    	// 输出克隆结果
    	fmt.Println("Original Product:", originalProduct.GetInfo())
    	fmt.Println("Cloned Product:", clonedProduct.GetInfo())
    }
    

    代码解释

    1. ProductPrototype 接口:定义了 Clone​ 方法,用于克隆商品对象。
    2. Product 结构体:实现了 ProductPrototype​ 接口中的 Clone​ 方法,提供商品信息 Name​ 和 Price​。
    3. Clone 方法:通过创建新实例并复制当前对象的值,实现商品对象的克隆。
    4. 主函数调用:在 main​ 函数中,创建了一个商品原型并通过 Clone​ 方法克隆商品实例。

    输出结果

    Original Product: Product Name: Laptop, Price: 1500.00
    Cloned Product: Product Name: Laptop, Price: 1500.00
    
  5. 单例-go

    以下是使用 Go 实现的单例模式示例代码,通过 CartService​ 确保每个用户会话中共享唯一的购物车实例。

    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    // CartService 购物车服务类,作为单例
    type CartService struct {
    	items []string
    }
    
    // 用于保存 CartService 单例实例
    var cartInstance *CartService
    var once sync.Once
    
    // GetInstance 返回唯一的购物车实例
    func GetInstance() *CartService {
    	once.Do(func() {
    		cartInstance = &CartService{}
    	})
    	return cartInstance
    }
    
    // AddItem 添加商品到购物车
    func (c *CartService) AddItem(item string) {
    	c.items = append(c.items, item)
    }
    
    // GetItems 获取购物车中的商品
    func (c *CartService) GetItems() []string {
    	return c.items
    }
    
    func main() {
    	// 获取购物车实例并添加商品
    	cart1 := GetInstance()
    	cart1.AddItem("Laptop")
    	cart1.AddItem("Phone")
    
    	// 获取同一个购物车实例并查看商品
    	cart2 := GetInstance()
    	fmt.Println("Cart items:", cart2.GetItems())
    
    	// cart1 和 cart2 是同一个实例
    	fmt.Printf("cart1 and cart2 are the same instance: %v\n", cart1 == cart2)
    }
    

    代码解释

    1. CartService:定义购物车服务类,包含商品列表 items​ 和添加商品的 AddItem​ 方法。
    2. 单例实现:通过 sync.Once​ 和 GetInstance​ 方法,确保 CartService​ 实例只创建一次,保证线程安全。
    3. 主函数调用:在 main​ 函数中,分别通过 GetInstance​ 获取购物车实例 cart1​ 和 cart2​,并验证它们是否为同一实例。

    输出结果

    Cart items: [Laptop Phone]
    cart1 and cart2 are the same instance: true
    
  6. 适配器-go

    以下是适配器模式在 Go 中的一个简易实现示例,通过 PaymentGatewayAdapter​ 将不同支付网关适配到统一的 processPayment​ 接口,方便在电商平台上统一调用。

    package main
    
    import "fmt"
    
    // PaymentProcessor 统一支付处理接口
    type PaymentProcessor interface {
    	ProcessPayment(amount float64) string
    }
    
    // PayPal 支付网关
    type PayPal struct{}
    
    func (p *PayPal) MakePayment(amount float64) string {
    	return fmt.Sprintf("Processed PayPal payment of $%.2f", amount)
    }
    
    // Stripe 支付网关
    type Stripe struct{}
    
    func (s *Stripe) Charge(amount float64) string {
    	return fmt.Sprintf("Processed Stripe payment of $%.2f", amount)
    }
    
    // PayPalAdapter 适配器,将 PayPal 适配到 PaymentProcessor 接口
    type PayPalAdapter struct {
    	paypal *PayPal
    }
    
    func (p *PayPalAdapter) ProcessPayment(amount float64) string {
    	return p.paypal.MakePayment(amount)
    }
    
    // StripeAdapter 适配器,将 Stripe 适配到 PaymentProcessor 接口
    type StripeAdapter struct {
    	stripe *Stripe
    }
    
    func (s *StripeAdapter) ProcessPayment(amount float64) string {
    	return s.stripe.Charge(amount)
    }
    
    func main() {
    	// 使用 PayPal 适配器
    	paypalAdapter := &PayPalAdapter{paypal: &PayPal{}}
    	fmt.Println(paypalAdapter.ProcessPayment(99.99))
    
    	// 使用 Stripe 适配器
    	stripeAdapter := &StripeAdapter{stripe: &Stripe{}}
    	fmt.Println(stripeAdapter.ProcessPayment(199.99))
    }
    

    代码解释

    1. PaymentProcessor 接口:定义了统一的 ProcessPayment​ 方法。
    2. PayPal 和 Stripe:表示具体支付网关,每个网关有自己特定的支付方法(如 MakePayment​ 和 Charge​)。
    3. PayPalAdapter 和 StripeAdapter:适配器类,分别将 PayPal​ 和 Stripe​ 的接口适配到统一的 ProcessPayment​ 接口。
    4. 主函数调用:在 main​ 函数中,通过 PayPalAdapter​ 和 StripeAdapter​ 适配器调用 ProcessPayment​,实现了统一的支付处理方式。

    输出结果

    Processed PayPal payment of $99.99
    Processed Stripe payment of $199.99
    
  7. 桥接-go

    下面是桥接模式在 Go 中的一个简易实现,通过 ProductInfo​ 和 DisplayPlatform​ 将商品信息和展示平台分离,为不同平台提供特定的展示方式。

    package main
    
    import "fmt"
    
    // DisplayPlatform 展示平台接口,提供展示方法
    type DisplayPlatform interface {
    	ShowDetails(name string, price float64)
    }
    
    // WebDisplay Web端展示平台
    type WebDisplay struct{}
    
    func (w *WebDisplay) ShowDetails(name string, price float64) {
    	fmt.Printf("Web Display -> Product: %s, Price: $%.2f\n", name, price)
    }
    
    // MobileDisplay 移动端展示平台
    type MobileDisplay struct{}
    
    func (m *MobileDisplay) ShowDetails(name string, price float64) {
    	fmt.Printf("Mobile Display -> Product: %s, Price: $%.2f\n", name, price)
    }
    
    // ProductInfo 商品信息类,使用展示平台接口
    type ProductInfo struct {
    	name     string
    	price    float64
    	platform DisplayPlatform
    }
    
    // NewProductInfo 构造函数
    func NewProductInfo(name string, price float64, platform DisplayPlatform) *ProductInfo {
    	return &ProductInfo{
    		name:     name,
    		price:    price,
    		platform: platform,
    	}
    }
    
    // ShowDetails 显示商品详细信息
    func (p *ProductInfo) ShowDetails() {
    	p.platform.ShowDetails(p.name, p.price)
    }
    
    func main() {
    	// 创建商品并在 Web 端展示
    	webProduct := NewProductInfo("Laptop", 1200.00, &WebDisplay{})
    	webProduct.ShowDetails()
    
    	// 创建商品并在移动端展示
    	mobileProduct := NewProductInfo("Laptop", 1200.00, &MobileDisplay{})
    	mobileProduct.ShowDetails()
    }
    

    代码解释

    1. DisplayPlatform 接口:定义了 ShowDetails​ 方法,用于不同平台的展示方式。
    2. WebDisplay 和 MobileDisplay:具体实现了 DisplayPlatform​,分别表示 Web 和移动端的展示逻辑。
    3. ProductInfo:持有商品信息及展示平台的实例,通过桥接模式将展示平台与商品信息分离。
    4. ShowDetails:调用展示平台的 ShowDetails​ 方法,实现商品信息在不同平台的展示。

    输出结果

    Web Display -> Product: Laptop, Price: $1200.00
    Mobile Display -> Product: Laptop, Price: $1200.00
    
  8. 组合-go

    下面是一个在 Go 中实现组合模式的简易代码示例,用于表示商品分类和子分类的树状结构,允许递归添加和显示分类。

    package main
    
    import (
    	"fmt"
    )
    
    // Category 表示一个商品分类接口,包含显示商品信息的方法
    type Category interface {
    	displayProducts(indent int)
    	addSubCategory(subCategory Category)
    }
    
    // BaseCategory 基础分类结构,实现通用的分类显示逻辑
    type BaseCategory struct {
    	name          string
    	subCategories []Category
    }
    
    // addSubCategory 添加子分类
    func (c *BaseCategory) addSubCategory(subCategory Category) {
    	c.subCategories = append(c.subCategories, subCategory)
    }
    
    // displayProducts 显示分类及其子分类的商品信息
    func (c *BaseCategory) displayProducts(indent int) {
    	// 输出当前分类
    	fmt.Printf("%s- %s\n", indentSpaces(indent), c.name)
    	// 递归输出子分类
    	for _, subCategory := range c.subCategories {
    		subCategory.displayProducts(indent + 2)
    	}
    }
    
    // indentSpaces 用于格式化输出的缩进
    func indentSpaces(count int) string {
    	return fmt.Sprintf("%*s", count, "")
    }
    
    // NewCategory 创建一个新的分类
    func NewCategory(name string) *BaseCategory {
    	return &BaseCategory{
    		name:          name,
    		subCategories: []Category{},
    	}
    }
    
    // MainCategory 顶级分类结构,继承自 BaseCategory
    type MainCategory struct {
    	BaseCategory
    }
    
    // SubCategory 子分类结构,继承自 BaseCategory
    type SubCategory struct {
    	BaseCategory
    }
    
    func main() {
    	// 创建顶级分类和子分类
    	root := &MainCategory{*NewCategory("电子产品")}
    	mobiles := &SubCategory{*NewCategory("手机")}
    	laptops := &SubCategory{*NewCategory("笔记本电脑")}
    
    	// 创建手机品牌子分类
    	apple := &SubCategory{*NewCategory("苹果")}
    	samsung := &SubCategory{*NewCategory("三星")}
    
    	// 创建笔记本电脑品牌子分类
    	dell := &SubCategory{*NewCategory("戴尔")}
    	lenovo := &SubCategory{*NewCategory("联想")}
    
    	// 构建分类树
    	root.addSubCategory(mobiles)
    	root.addSubCategory(laptops)
    	mobiles.addSubCategory(apple)
    	mobiles.addSubCategory(samsung)
    	laptops.addSubCategory(dell)
    	laptops.addSubCategory(lenovo)
    
    	// 显示所有分类
    	root.displayProducts(0)
    }
    

    输出结果

    运行该代码,将会输出以下商品分类结构:

    - 电子产品
      - 手机
        - 苹果
        - 三星
      - 笔记本电脑
        - 戴尔
        - 联想
    

    说明

    • Category​接口定义了基本的分类行为。
    • BaseCategory​ 实现了基础的分类显示和子分类管理。
    • MainCategory​ 和 SubCategory​继承 BaseCategory​,实现具体的分类实例。
    • displayProducts​ 方法递归调用,便于展示和管理嵌套的分类结构。
  9. 装饰-go

    下面是一个在 Go 中实现装饰模式的简易代码示例,用于在商品详情页动态添加促销和折扣信息,以实现多样化的商品描述。

    package main
    
    import (
    	"fmt"
    )
    
    // Product 接口定义了商品的基本行为
    type Product interface {
    	getDescription() string
    }
    
    // BaseProduct 具体商品结构,实现基础的商品描述
    type BaseProduct struct {
    	name        string
    	price       float64
    	description string
    }
    
    // getDescription 返回基础商品的描述
    func (p *BaseProduct) getDescription() string {
    	return fmt.Sprintf("%s: %.2f", p.name, p.price)
    }
    
    // NewBaseProduct 创建一个新的基础商品
    func NewBaseProduct(name string, price float64, description string) *BaseProduct {
    	return &BaseProduct{name: name, price: price, description: description}
    }
    
    // ProductDecorator 装饰器结构,持有一个 Product 对象
    type ProductDecorator struct {
    	product Product
    }
    
    // NewProductDecorator 创建一个新的装饰器
    func NewProductDecorator(p Product) *ProductDecorator {
    	return &ProductDecorator{product: p}
    }
    
    // PromotionalDecorator 促销装饰器
    type PromotionalDecorator struct {
    	ProductDecorator
    	promotion string
    }
    
    // getDescription 返回带促销信息的商品描述
    func (d *PromotionalDecorator) getDescription() string {
    	return fmt.Sprintf("%s - 促销: %s", d.product.getDescription(), d.promotion)
    }
    
    // DiscountDecorator 折扣装饰器
    type DiscountDecorator struct {
    	ProductDecorator
    	discount float64
    }
    
    // getDescription 返回带折扣信息的商品描述
    func (d *DiscountDecorator) getDescription() string {
    	return fmt.Sprintf("%s - 折扣: %.2f%%", d.product.getDescription(), d.discount)
    }
    
    func main() {
    	// 创建基础商品
    	product := NewBaseProduct("智能手机", 599.99, "最新款智能手机")
    
    	// 添加促销装饰
    	promotionalProduct := &PromotionalDecorator{
    		ProductDecorator: ProductDecorator{product: product},
    		promotion:        "限时特价",
    	}
    
    	// 添加折扣装饰
    	discountedProduct := &DiscountDecorator{
    		ProductDecorator: ProductDecorator{product: promotionalProduct},
    		discount:         15,
    	}
    
    	// 输出商品描述
    	fmt.Println(discountedProduct.getDescription())
    }
    

    输出结果

    运行该代码,将会输出以下商品描述:

    智能手机: 599.99 - 促销: 限时特价 - 折扣: 15.00%
    

    说明

    • Product​ 接口定义了商品的基本行为。
    • BaseProduct​ 结构实现了基础商品的描述。
    • ProductDecorator​ 是装饰器的基础结构,持有一个 Product​ 对象。
    • PromotionalDecorator​ 和 DiscountDecorator​ 分别用于动态添加促销和折扣信息。
    • 通过嵌套装饰器,可以灵活地组合不同的装饰功能而不修改基础商品对象。
  10. 外观-go

    以下是一个在 Go 中实现外观模式的简易代码示例,用于简化用户下单时涉及的支付、库存和配送等模块的调用。

    package main
    
    import (
    	"fmt"
    )
    
    // PaymentService 支付服务
    type PaymentService struct{}
    
    func (p *PaymentService) processPayment(amount float64) {
    	fmt.Printf("支付处理: %.2f 元\n", amount)
    }
    
    // InventoryService 库存服务
    type InventoryService struct{}
    
    func (i *InventoryService) checkInventory(productID int) bool {
    	// 假设所有产品都有库存
    	fmt.Printf("检查库存: 产品ID %d - 库存充足\n", productID)
    	return true
    }
    
    // ShippingService 配送服务
    type ShippingService struct{}
    
    func (s *ShippingService) shipOrder(orderID int) {
    	fmt.Printf("配送订单: 订单ID %d\n", orderID)
    }
    
    // OrderFacade 外观模式,简化下单流程
    type OrderFacade struct {
    	paymentService   *PaymentService
    	inventoryService *InventoryService
    	shippingService  *ShippingService
    }
    
    func NewOrderFacade() *OrderFacade {
    	return &OrderFacade{
    		paymentService:   &PaymentService{},
    		inventoryService: &InventoryService{},
    		shippingService:  &ShippingService{},
    	}
    }
    
    // processOrder 处理下单流程
    func (o *OrderFacade) processOrder(productID int, amount float64) {
    	if o.inventoryService.checkInventory(productID) {
    		o.paymentService.processPayment(amount)
    		o.shippingService.shipOrder(productID) // 这里使用产品ID作为订单ID示例
    		fmt.Println("订单处理成功!")
    	} else {
    		fmt.Println("库存不足,无法处理订单.")
    	}
    }
    
    func main() {
    	orderFacade := NewOrderFacade()
    	orderFacade.processOrder(101, 299.99) // 假设产品ID为101,支付299.99元
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    检查库存: 产品ID 101 - 库存充足
    支付处理: 299.99 元
    配送订单: 订单ID 101
    订单处理成功!
    

    说明

    • PaymentService​、InventoryService​ 和 ShippingService​ 分别代表支付、库存和配送的服务模块。
    • OrderFacade​ 是外观类,它将多个服务组合在一起,通过统一的 processOrder​ 方法来简化客户端操作。
    • 客户端只需要调用 OrderFacade​ 的 processOrder​ 方法,而不需要了解内部服务的具体实现,从而简化了下单流程的复杂性。
  11. 享元-go

    以下是一个在 Go 中实现享元模式的简易代码示例,用于共享商品图片资源,以避免内存浪费。

    package main
    
    import (
    	"fmt"
    )
    
    // ProductImage 享元类
    type ProductImage struct {
    	imagePath string
    }
    
    // NewProductImage 创建新的商品图片
    func NewProductImage(imagePath string) *ProductImage {
    	return &ProductImage{imagePath: imagePath}
    }
    
    // Display 显示商品图片
    func (p *ProductImage) Display() {
    	fmt.Printf("显示商品图片: %s\n", p.imagePath)
    }
    
    // ImageFactory 享元工厂
    type ImageFactory struct {
    	imageMap map[string]*ProductImage
    }
    
    // NewImageFactory 创建新的图片工厂
    func NewImageFactory() *ImageFactory {
    	return &ImageFactory{imageMap: make(map[string]*ProductImage)}
    }
    
    // GetImage 获取共享的商品图片
    func (f *ImageFactory) GetImage(imagePath string) *ProductImage {
    	// 如果图片已经存在,则返回共享的实例
    	if img, exists := f.imageMap[imagePath]; exists {
    		return img
    	}
    	// 否则创建新的图片对象并存储
    	img := NewProductImage(imagePath)
    	f.imageMap[imagePath] = img
    	return img
    }
    
    // Client 客户端
    type Client struct {
    	factory *ImageFactory
    }
    
    // NewClient 创建新的客户端
    func NewClient(factory *ImageFactory) *Client {
    	return &Client{factory: factory}
    }
    
    // AddProductImage 添加商品图片
    func (c *Client) AddProductImage(imagePath string) {
    	image := c.factory.GetImage(imagePath)
    	image.Display()
    }
    
    func main() {
    	factory := NewImageFactory()
    	client := NewClient(factory)
    
    	// 使用相同的图片路径
    	client.AddProductImage("images/product1.jpg")
    	client.AddProductImage("images/product2.jpg")
    	client.AddProductImage("images/product1.jpg") // 共享同一图片
    	client.AddProductImage("images/product3.jpg")
    	client.AddProductImage("images/product2.jpg") // 共享同一图片
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    显示商品图片: images/product1.jpg
    显示商品图片: images/product2.jpg
    显示商品图片: images/product1.jpg
    显示商品图片: images/product3.jpg
    显示商品图片: images/product2.jpg
    

    说明

    • ProductImage​ 类代表商品图片对象,其中包含 imagePath​ 属性。
    • ImageFactory​ 是享元工厂,负责管理和共享 ProductImage​ 实例。如果请求的图片路径已经存在,则返回已有的实例;否则,创建新的实例并存储。
    • Client​ 类代表客户端,它通过 ImageFactory​ 来获取和显示商品图片。
    • 运行时,通过添加相同的图片路径,可以看到同一图片对象被多次使用,这实现了享元模式的核心思想:通过共享相同的对象来节省内存。
  12. 代理-go

    以下是一个在 Go 中实现代理模式的简易代码示例,用于控制用户的订单操作权限,如顾客只能查看订单状态,管理员可以取消订单。

    package main
    
    import (
    	"fmt"
    )
    
    // Order 订单类
    type Order struct {
    	ID     int
    	Status string
    }
    
    // OrderService 订单服务接口
    type OrderService interface {
    	ViewOrder(orderID int) string
    	CancelOrder(orderID int) string
    }
    
    // RealOrderService 真实订单服务
    type RealOrderService struct {
    	orders map[int]*Order
    }
    
    // NewRealOrderService 创建新的真实订单服务
    func NewRealOrderService() *RealOrderService {
    	return &RealOrderService{
    		orders: map[int]*Order{
    			1: {ID: 1, Status: "待发货"},
    			2: {ID: 2, Status: "已发货"},
    		},
    	}
    }
    
    // ViewOrder 查看订单状态
    func (s *RealOrderService) ViewOrder(orderID int) string {
    	if order, exists := s.orders[orderID]; exists {
    		return fmt.Sprintf("订单ID: %d,状态: %s", order.ID, order.Status)
    	}
    	return "订单不存在"
    }
    
    // CancelOrder 取消订单
    func (s *RealOrderService) CancelOrder(orderID int) string {
    	if order, exists := s.orders[orderID]; exists {
    		order.Status = "已取消"
    		return fmt.Sprintf("订单ID: %d,已取消", order.ID)
    	}
    	return "订单不存在"
    }
    
    // OrderProxy 代理类
    type OrderProxy struct {
    	realService *RealOrderService
    	isAdmin     bool
    }
    
    // NewOrderProxy 创建新的订单代理
    func NewOrderProxy(realService *RealOrderService, isAdmin bool) *OrderProxy {
    	return &OrderProxy{realService: realService, isAdmin: isAdmin}
    }
    
    // ViewOrder 查看订单状态
    func (p *OrderProxy) ViewOrder(orderID int) string {
    	return p.realService.ViewOrder(orderID)
    }
    
    // CancelOrder 取消订单
    func (p *OrderProxy) CancelOrder(orderID int) string {
    	if p.isAdmin {
    		return p.realService.CancelOrder(orderID)
    	}
    	return "权限不足,无法取消订单"
    }
    
    // Client 客户端
    type Client struct {
    	orderService OrderService
    }
    
    // NewClient 创建新的客户端
    func NewClient(orderService OrderService) *Client {
    	return &Client{orderService: orderService}
    }
    
    // Main 函数
    func main() {
    	// 创建真实订单服务
    	realService := NewRealOrderService()
    
    	// 创建代理,顾客用户
    	customerProxy := NewOrderProxy(realService, false)
    	client1 := NewClient(customerProxy)
    
    	fmt.Println(client1.orderService.ViewOrder(1))   // 顾客查看订单
    	fmt.Println(client1.orderService.CancelOrder(1)) // 顾客尝试取消订单
    
    	// 创建代理,管理员用户
    	adminProxy := NewOrderProxy(realService, true)
    	client2 := NewClient(adminProxy)
    
    	fmt.Println(client2.orderService.ViewOrder(2))   // 管理员查看订单
    	fmt.Println(client2.orderService.CancelOrder(2)) // 管理员取消订单
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    订单ID: 1,状态: 待发货
    权限不足,无法取消订单
    订单ID: 2,状态: 已发货
    订单ID: 2,已取消
    

    说明

    • Order​ 类表示一个订单,包含订单 ID 和状态。
    • OrderService​ 接口定义了查看和取消订单的方法。
    • RealOrderService​ 实现了 OrderService​ 接口,提供实际的订单处理逻辑。
    • OrderProxy​ 代理类用于控制对订单服务的访问。根据用户权限(普通用户或管理员),决定是否允许取消订单。
    • Client​ 类代表客户端,它使用代理来访问订单服务。
    • 在主函数中,通过不同的代理实例展示了普通用户和管理员用户对订单的不同操作权限。
  13. 责任链-go

    以下是一个在 Go 中实现责任链模式的简易代码示例,用于订单处理流程,依次经过库存检查、支付确认和配送等多个步骤。

    package main
    
    import (
    	"fmt"
    )
    
    // Order 订单类
    type Order struct {
    	ID      int
    	Amount  float64
    	Stocked bool
    	Paid    bool
    }
    
    // OrderHandler 订单处理器接口
    type OrderHandler interface {
    	SetNext(handler OrderHandler) OrderHandler
    	Handle(order *Order) bool
    }
    
    // BaseHandler 基础处理器
    type BaseHandler struct {
    	next OrderHandler
    }
    
    // SetNext 设置下一个处理器
    func (h *BaseHandler) SetNext(handler OrderHandler) OrderHandler {
    	h.next = handler
    	return handler
    }
    
    // Handle 处理方法,留给子类实现
    func (h *BaseHandler) Handle(order *Order) bool {
    	if h.next != nil {
    		return h.next.Handle(order)
    	}
    	return true
    }
    
    // StockCheckHandler 库存检查处理器
    type StockCheckHandler struct {
    	BaseHandler
    }
    
    // Handle 库存检查处理逻辑
    func (h *StockCheckHandler) Handle(order *Order) bool {
    	if order.Stocked {
    		fmt.Printf("订单 %d 库存检查通过。\n", order.ID)
    		return h.BaseHandler.Handle(order)
    	}
    	fmt.Printf("订单 %d 库存不足,处理失败。\n", order.ID)
    	return false
    }
    
    // PaymentHandler 支付确认处理器
    type PaymentHandler struct {
    	BaseHandler
    }
    
    // Handle 支付确认逻辑
    func (h *PaymentHandler) Handle(order *Order) bool {
    	if order.Paid {
    		fmt.Printf("订单 %d 支付确认通过。\n", order.ID)
    		return h.BaseHandler.Handle(order)
    	}
    	fmt.Printf("订单 %d 支付未完成,处理失败。\n", order.ID)
    	return false
    }
    
    // DeliveryHandler 配送处理器
    type DeliveryHandler struct {
    	BaseHandler
    }
    
    // Handle 配送逻辑
    func (h *DeliveryHandler) Handle(order *Order) bool {
    	fmt.Printf("订单 %d 配送中...\n", order.ID)
    	return h.BaseHandler.Handle(order)
    }
    
    // Main 函数
    func main() {
    	// 创建订单
    	order := &Order{
    		ID:      1,
    		Amount:  100.0,
    		Stocked: true,
    		Paid:    true,
    	}
    
    	// 创建责任链
    	stockCheck := &StockCheckHandler{}
    	payment := &PaymentHandler{}
    	delivery := &DeliveryHandler{}
    
    	// 设置责任链
    	stockCheck.SetNext(payment).SetNext(delivery)
    
    	// 开始处理订单
    	fmt.Println("处理订单...")
    	stockCheck.Handle(order)
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    处理订单...
    订单 1 库存检查通过。
    订单 1 支付确认通过。
    订单 1 配送中...
    

    说明

    • Order​ 类表示一个订单,包含订单 ID、金额、库存状态和支付状态。
    • OrderHandler​ 接口定义了责任链中的处理器方法,包括设置下一个处理器和处理订单的逻辑。
    • BaseHandler​ 是一个基础处理器,负责管理责任链中的下一个处理器。
    • StockCheckHandler​、PaymentHandler​ 和 DeliveryHandler​ 分别实现了库存检查、支付确认和配送的处理逻辑。
    • 在主函数中,创建一个订单和责任链,依次调用处理器进行订单处理。通过责任链模式,可以灵活地调整和扩展处理步骤。

    4o mini

  14. 命令-go

    以下是一个在 Go 中实现命令模式的简易代码示例,使用 CartCommand​ 类来管理用户的购物车操作,包括添加商品和移除商品的操作,并支持撤销和重做功能。

    package main
    
    import (
    	"fmt"
    )
    
    // Command 接口定义了命令的基本方法
    type Command interface {
    	Execute()
    	Undo()
    }
    
    // Product 商品类
    type Product struct {
    	Name  string
    	Price float64
    }
    
    // Cart 购物车类
    type Cart struct {
    	Items []Product
    }
    
    // AddProductCommand 添加商品命令
    type AddProductCommand struct {
    	Cart    *Cart
    	Product Product
    }
    
    // Execute 执行添加商品命令
    func (c *AddProductCommand) Execute() {
    	c.Cart.Items = append(c.Cart.Items, c.Product)
    	fmt.Printf("添加商品: %s\n", c.Product.Name)
    }
    
    // Undo 撤销添加商品命令
    func (c *AddProductCommand) Undo() {
    	c.Cart.Items = c.Cart.Items[:len(c.Cart.Items)-1]
    	fmt.Printf("撤销添加商品: %s\n", c.Product.Name)
    }
    
    // RemoveProductCommand 移除商品命令
    type RemoveProductCommand struct {
    	Cart    *Cart
    	Product Product
    }
    
    // Execute 执行移除商品命令
    func (c *RemoveProductCommand) Execute() {
    	for i, item := range c.Cart.Items {
    		if item.Name == c.Product.Name {
    			c.Cart.Items = append(c.Cart.Items[:i], c.Cart.Items[i+1:]...)
    			fmt.Printf("移除商品: %s\n", c.Product.Name)
    			break
    		}
    	}
    }
    
    // Undo 撤销移除商品命令
    func (c *RemoveProductCommand) Undo() {
    	c.Cart.Items = append(c.Cart.Items, c.Product)
    	fmt.Printf("撤销移除商品: %s\n", c.Product.Name)
    }
    
    // Invoker 命令调用者
    type Invoker struct {
    	commands []Command
    }
    
    // ExecuteCommand 执行命令
    func (i *Invoker) ExecuteCommand(command Command) {
    	command.Execute()
    	i.commands = append(i.commands, command)
    }
    
    // UndoCommand 撤销最后一个命令
    func (i *Invoker) UndoCommand() {
    	if len(i.commands) > 0 {
    		lastCommand := i.commands[len(i.commands)-1]
    		lastCommand.Undo()
    		i.commands = i.commands[:len(i.commands)-1]
    	}
    }
    
    // Main 函数
    func main() {
    	cart := &Cart{}
    
    	invoker := &Invoker{}
    
    	// 创建并执行添加商品命令
    	addProduct1 := &AddProductCommand{Cart: cart, Product: Product{Name: "商品A", Price: 100.0}}
    	invoker.ExecuteCommand(addProduct1)
    
    	addProduct2 := &AddProductCommand{Cart: cart, Product: Product{Name: "商品B", Price: 200.0}}
    	invoker.ExecuteCommand(addProduct2)
    
    	// 创建并执行移除商品命令
    	removeProduct := &RemoveProductCommand{Cart: cart, Product: Product{Name: "商品A", Price: 100.0}}
    	invoker.ExecuteCommand(removeProduct)
    
    	// 撤销最后一个命令(移除商品A)
    	invoker.UndoCommand()
    
    	// 输出购物车当前状态
    	fmt.Println("购物车商品列表:")
    	for _, item := range cart.Items {
    		fmt.Printf("商品: %s, 价格: %.2f\n", item.Name, item.Price)
    	}
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    添加商品: 商品A
    添加商品: 商品B
    移除商品: 商品A
    撤销移除商品: 商品A
    购物车商品列表:
    商品: 商品A, 价格: 100.00
    商品: 商品B, 价格: 200.00
    

    说明

    • Command​ 接口定义了命令的基本方法 Execute()​ 和 Undo()​。
    • Product​ 类表示一个商品,包含商品名称和价格。
    • Cart​ 类表示购物车,包含商品列表。
    • AddProductCommand​ 和 RemoveProductCommand​ 分别实现了添加和移除商品的命令。
    • Invoker​ 类用于执行命令并维护已执行命令的列表,以支持撤销操作。
    • 在主函数中,创建一个购物车和命令调用者,执行添加和移除商品的命令,并进行撤销操作,最终输出购物车的当前状态。
  15. 迭代器-go

    以下是一个在 Go 中实现迭代器模式的简易代码示例,使用 ProductIterator​ 类来迭代商品列表,以支持浏览商品的操作。

    package main
    
    import "fmt"
    
    // Product 商品类
    type Product struct {
    	Name  string
    	Price float64
    }
    
    // ProductCollection 商品集合接口
    type ProductCollection interface {
    	CreateIterator() Iterator
    }
    
    // Iterator 迭代器接口
    type Iterator interface {
    	Next() *Product
    	HasNext() bool
    }
    
    // ProductList 商品列表
    type ProductList struct {
    	products []Product
    }
    
    // CreateIterator 创建商品迭代器
    func (p *ProductList) CreateIterator() Iterator {
    	return &ProductIterator{
    		products: p.products,
    		index:    0,
    	}
    }
    
    // ProductIterator 商品迭代器
    type ProductIterator struct {
    	products []Product
    	index    int
    }
    
    // HasNext 判断是否还有下一个商品
    func (pi *ProductIterator) HasNext() bool {
    	return pi.index < len(pi.products)
    }
    
    // Next 获取下一个商品
    func (pi *ProductIterator) Next() *Product {
    	if pi.HasNext() {
    		product := &pi.products[pi.index]
    		pi.index++
    		return product
    	}
    	return nil
    }
    
    // Main 函数
    func main() {
    	// 创建商品列表
    	productList := &ProductList{
    		products: []Product{
    			{Name: "商品A", Price: 100.0},
    			{Name: "商品B", Price: 200.0},
    			{Name: "商品C", Price: 300.0},
    		},
    	}
    
    	// 创建迭代器
    	iterator := productList.CreateIterator()
    
    	// 遍历商品列表
    	fmt.Println("商品列表:")
    	for iterator.HasNext() {
    		product := iterator.Next()
    		fmt.Printf("商品名称: %s, 价格: %.2f\n", product.Name, product.Price)
    	}
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    商品列表:
    商品名称: 商品A, 价格: 100.00
    商品名称: 商品B, 价格: 200.00
    商品名称: 商品C, 价格: 300.00
    

    说明

    • Product​ 类表示一个商品,包含商品名称和价格。
    • ProductCollection​ 接口定义了创建迭代器的方法。
    • Iterator​ 接口定义了 Next()​ 和 HasNext()​ 方法。
    • ProductList​ 实现了 ProductCollection​ 接口,并包含商品列表。
    • ProductIterator​ 实现了 Iterator​ 接口,用于迭代 ProductList​ 中的商品。
    • 在主函数中,创建一个商品列表和相应的迭代器,遍历商品并输出每个商品的名称和价格。
  16. 中介者-go

    以下是一个在 Go 中实现中介者模式的简易代码示例,使用 CheckoutMediator​ 类来协调支付、库存和物流模块的交互,从而避免直接耦合。

    package main
    
    import "fmt"
    
    // Mediator 中介者接口
    type Mediator interface {
    	Notify(colleague Colleague, event string)
    }
    
    // Colleague 同事接口
    type Colleague interface {
    	SetMediator(mediator Mediator)
    }
    
    // Payment 支付模块
    type Payment struct {
    	mediator Mediator
    }
    
    func (p *Payment) SetMediator(mediator Mediator) {
    	p.mediator = mediator
    }
    
    func (p *Payment) ProcessPayment() {
    	fmt.Println("处理支付...")
    	p.mediator.Notify(p, "payment_processed")
    }
    
    // Inventory 库存模块
    type Inventory struct {
    	mediator Mediator
    }
    
    func (i *Inventory) SetMediator(mediator Mediator) {
    	i.mediator = mediator
    }
    
    func (i *Inventory) UpdateInventory() {
    	fmt.Println("更新库存...")
    	i.mediator.Notify(i, "inventory_updated")
    }
    
    // Logistics 物流模块
    type Logistics struct {
    	mediator Mediator
    }
    
    func (l *Logistics) SetMediator(mediator Mediator) {
    	l.mediator = mediator
    }
    
    func (l *Logistics) ShipOrder() {
    	fmt.Println("发货中...")
    }
    
    // CheckoutMediator 结算中介者
    type CheckoutMediator struct {
    	payment   *Payment
    	inventory *Inventory
    	logistics *Logistics
    }
    
    // Notify 通知各模块
    func (cm *CheckoutMediator) Notify(colleague Colleague, event string) {
    	switch event {
    	case "payment_processed":
    		cm.inventory.UpdateInventory()
    		cm.logistics.ShipOrder()
    	case "inventory_updated":
    		fmt.Println("库存已更新,准备发货。")
    	}
    }
    
    // Main 函数
    func main() {
    	// 创建中介者和模块
    	mediator := &CheckoutMediator{}
    
    	payment := &Payment{}
    	inventory := &Inventory{}
    	logistics := &Logistics{}
    
    	// 设置中介者
    	payment.SetMediator(mediator)
    	inventory.SetMediator(mediator)
    	logistics.SetMediator(mediator)
    
    	// 将模块添加到中介者
    	mediator.payment = payment
    	mediator.inventory = inventory
    	mediator.logistics = logistics
    
    	// 模拟订单结算流程
    	payment.ProcessPayment()
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    处理支付...
    更新库存...
    发货中...
    库存已更新,准备发货。
    

    说明

    • Mediator​ 接口定义了通知方法,用于协调各模块的交互。
    • Colleague​ 接口定义了设置中介者的方法。
    • Payment​、Inventory​ 和 Logistics​ 分别表示支付、库存和物流模块,实现了 Colleague​ 接口,并通过中介者与其他模块交互。
    • CheckoutMediator​ 实现了 Mediator​ 接口,负责协调各模块的行为。
    • 在主函数中,创建中介者和模块实例,设置中介者,并模拟订单结算过程,通过支付模块触发流程,其他模块随之执行。
  17. 备忘录-go

    以下是一个在 Go 中实现备忘录模式的简易代码示例,使用 OrderStateMemento​ 类来保存和恢复订单的状态,以便在用户修改订单时进行回退或恢复操作。

    package main
    
    import "fmt"
    
    // Memento 备忘录类
    type Memento struct {
    	state string
    }
    
    // Order 订单类
    type Order struct {
    	state string
    }
    
    // Save 保存当前状态到备忘录
    func (o *Order) Save() *Memento {
    	fmt.Println("保存当前订单状态:", o.state)
    	return &Memento{state: o.state}
    }
    
    // Restore 从备忘录恢复状态
    func (o *Order) Restore(m *Memento) {
    	o.state = m.state
    	fmt.Println("恢复订单状态:", o.state)
    }
    
    // SetState 设置订单状态
    func (o *Order) SetState(state string) {
    	o.state = state
    	fmt.Println("订单状态更新为:", o.state)
    }
    
    // Main 函数
    func main() {
    	// 创建订单实例
    	order := &Order{}
    
    	// 修改订单状态并保存
    	order.SetState("已创建")
    	memento1 := order.Save()
    
    	order.SetState("已支付")
    	memento2 := order.Save()
    
    	order.SetState("已发货")
    
    	// 恢复至之前状态
    	order.Restore(memento2) // 恢复至“已支付”状态
    	order.Restore(memento1) // 恢复至“已创建”状态
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    订单状态更新为: 已创建
    保存当前订单状态: 已创建
    订单状态更新为: 已支付
    保存当前订单状态: 已支付
    订单状态更新为: 已发货
    恢复订单状态: 已支付
    恢复订单状态: 已创建
    

    说明

    • Memento​ 类用于保存订单的状态。
    • Order​ 类表示订单,包含当前状态,并提供保存和恢复状态的方法。
    • Save()​ 方法将当前状态保存到备忘录中,返回 Memento​ 对象。
    • Restore()​ 方法从 Memento​ 对象中恢复状态。
    • SetState()​ 方法用于更新订单状态。
    • 在主函数中,创建订单实例,修改状态并保存,之后恢复至之前的状态,展示了备忘录模式的应用。
  18. 观察者-go

    以下是一个在 Go 中实现观察者模式的简易代码示例,使用 OrderStatusObserver​ 类来观察订单状态的变化,并在状态更新时通知用户和物流系统。

    package main
    
    import (
    	"fmt"
    )
    
    // Observer 观察者接口
    type Observer interface {
    	update(orderID string, status string)
    }
    
    // Subject 主题接口
    type Subject interface {
    	registerObserver(o Observer)
    	removeObserver(o Observer)
    	notifyObservers()
    }
    
    // Order 订单类
    type Order struct {
    	observers []Observer
    	orderID   string
    	status    string
    }
    
    // NewOrder 创建新订单
    func NewOrder(orderID string) *Order {
    	return &Order{
    		orderID: orderID,
    	}
    }
    
    // registerObserver 注册观察者
    func (o *Order) registerObserver(observer Observer) {
    	o.observers = append(o.observers, observer)
    }
    
    // removeObserver 移除观察者
    func (o *Order) removeObserver(observer Observer) {
    	for i, obs := range o.observers {
    		if obs == observer {
    			o.observers = append(o.observers[:i], o.observers[i+1:]...)
    			break
    		}
    	}
    }
    
    // notifyObservers 通知所有观察者
    func (o *Order) notifyObservers() {
    	for _, observer := range o.observers {
    		observer.update(o.orderID, o.status)
    	}
    }
    
    // UpdateStatus 更新订单状态并通知观察者
    func (o *Order) UpdateStatus(status string) {
    	o.status = status
    	fmt.Printf("订单 %s 状态更新为: %s\n", o.orderID, status)
    	o.notifyObservers()
    }
    
    // User 用户观察者
    type User struct {
    	name string
    }
    
    // update 用户更新通知
    func (u *User) update(orderID string, status string) {
    	fmt.Printf("用户 %s 收到通知: 订单 %s 状态更新为: %s\n", u.name, orderID, status)
    }
    
    // Logistics 物流观察者
    type Logistics struct{}
    
    // update 物流系统更新通知
    func (l *Logistics) update(orderID string, status string) {
    	fmt.Printf("物流系统收到通知: 订单 %s 状态更新为: %s\n", orderID, status)
    }
    
    // Main 函数
    func main() {
    	// 创建订单实例
    	order := NewOrder("12345")
    
    	// 创建用户和物流实例
    	user1 := &User{name: "Alice"}
    	user2 := &User{name: "Bob"}
    	logistics := &Logistics{}
    
    	// 注册观察者
    	order.registerObserver(user1)
    	order.registerObserver(user2)
    	order.registerObserver(logistics)
    
    	// 更新订单状态
    	order.UpdateStatus("已发货")
    	order.UpdateStatus("已送达")
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    订单 12345 状态更新为: 已发货
    用户 Alice 收到通知: 订单 12345 状态更新为: 已发货
    用户 Bob 收到通知: 订单 12345 状态更新为: 已发货
    物流系统收到通知: 订单 12345 状态更新为: 已发货
    订单 12345 状态更新为: 已送达
    用户 Alice 收到通知: 订单 12345 状态更新为: 已送达
    用户 Bob 收到通知: 订单 12345 状态更新为: 已送达
    物流系统收到通知: 订单 12345 状态更新为: 已送达
    

    说明

    • Observer​ 接口定义了观察者应实现的 update()​ 方法,用于接收状态更新通知。
    • Subject​ 接口定义了主题的方法,包括注册、移除和通知观察者。
    • Order​ 类实现了 Subject​ 接口,维护观察者列表,并在状态更新时通知所有观察者。
    • User​ 和 Logistics​ 类实现了 Observer​ 接口,分别表示用户和物流系统。
    • 在主函数中,创建订单实例、用户和物流观察者,注册观察者,并在更新订单状态时通知所有观察者,展示了观察者模式的应用。
  19. 状态-go

    以下是一个在 Go 中实现状态模式的简易代码示例,使用 OrderState​ 类来管理订单的不同状态(如已下单、已发货、已收货、完成)。

    package main
    
    import (
    	"fmt"
    )
    
    // OrderState 订单状态接口
    type OrderState interface {
    	nextState(order *Order)
    	getStatus() string
    }
    
    // Order 订单结构
    type Order struct {
    	state OrderState
    }
    
    // NewOrder 创建新订单,初始状态为已下单
    func NewOrder() *Order {
    	order := &Order{}
    	order.setState(&OrderedState{}) // 初始状态
    	return order
    }
    
    // setState 设置订单状态
    func (o *Order) setState(state OrderState) {
    	o.state = state
    	fmt.Printf("订单状态更新为: %s\n", o.state.getStatus())
    }
    
    // nextState 触发状态转移
    func (o *Order) nextState() {
    	o.state.nextState(o)
    }
    
    // OrderedState 已下单状态
    type OrderedState struct{}
    
    // nextState 处理状态转移逻辑
    func (s *OrderedState) nextState(order *Order) {
    	order.setState(&ShippedState{}) // 转换为已发货状态
    }
    
    // getStatus 获取当前状态
    func (s *OrderedState) getStatus() string {
    	return "已下单"
    }
    
    // ShippedState 已发货状态
    type ShippedState struct{}
    
    // nextState 处理状态转移逻辑
    func (s *ShippedState) nextState(order *Order) {
    	order.setState(&DeliveredState{}) // 转换为已收货状态
    }
    
    // getStatus 获取当前状态
    func (s *ShippedState) getStatus() string {
    	return "已发货"
    }
    
    // DeliveredState 已收货状态
    type DeliveredState struct{}
    
    // nextState 处理状态转移逻辑
    func (s *DeliveredState) nextState(order *Order) {
    	order.setState(&CompletedState{}) // 转换为完成状态
    }
    
    // getStatus 获取当前状态
    func (s *DeliveredState) getStatus() string {
    	return "已收货"
    }
    
    // CompletedState 完成状态
    type CompletedState struct{}
    
    // nextState 处理状态转移逻辑
    func (s *CompletedState) nextState(order *Order) {
    	fmt.Println("订单已完成,无法转移到其他状态。")
    }
    
    // getStatus 获取当前状态
    func (s *CompletedState) getStatus() string {
    	return "已完成"
    }
    
    // Main 函数
    func main() {
    	order := NewOrder() // 创建新订单
    
    	// 触发状态转移
    	order.nextState() // 已下单 -> 已发货
    	order.nextState() // 已发货 -> 已收货
    	order.nextState() // 已收货 -> 已完成
    	order.nextState() // 已完成 -> 不再转移
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    订单状态更新为: 已下单
    订单状态更新为: 已发货
    订单状态更新为: 已收货
    订单状态更新为: 已完成
    订单已完成,无法转移到其他状态。
    

    说明

    • OrderState​ 接口定义了状态的行为,包括 nextState()​ 方法用于处理状态转移,以及 getStatus()​ 方法用于获取当前状态的描述。
    • Order​ 类代表一个订单,维护当前状态,并提供方法以触发状态转移。
    • 每个具体状态(如 OrderedState​、ShippedState​、DeliveredState​ 和 CompletedState​)实现了 OrderState​ 接口,封装了状态转移的逻辑。
    • 在主函数中,创建新订单并依次触发状态转移,展示了状态模式的应用,确保状态变化符合业务规则。
  20. 策略-go

    以下是一个在 Go 中实现策略模式的简易代码示例,使用 DiscountStrategy​ 类来动态选择不同的折扣策略(如满减、折扣、赠品)进行商品折扣计算。

    package main
    
    import (
    	"fmt"
    )
    
    // DiscountStrategy 折扣策略接口
    type DiscountStrategy interface {
    	applyDiscount(price float64) float64
    }
    
    // FullReductionStrategy 满减策略
    type FullReductionStrategy struct {
    	threshold float64 // 满足条件的金额
    	reduction float64 // 减去的金额
    }
    
    // applyDiscount 实现满减策略
    func (s *FullReductionStrategy) applyDiscount(price float64) float64 {
    	if price >= s.threshold {
    		return price - s.reduction
    	}
    	return price
    }
    
    // PercentageDiscountStrategy 折扣策略
    type PercentageDiscountStrategy struct {
    	percentage float64 // 折扣百分比
    }
    
    // applyDiscount 实现折扣策略
    func (s *PercentageDiscountStrategy) applyDiscount(price float64) float64 {
    	return price * (1 - s.percentage/100)
    }
    
    // GiftStrategy 赠品策略
    type GiftStrategy struct {
    	giftValue float64 // 赠品的价值
    }
    
    // applyDiscount 实现赠品策略
    func (s *GiftStrategy) applyDiscount(price float64) float64 {
    	return price // 赠品策略不影响商品价格
    }
    
    // ShoppingCart 购物车结构
    type ShoppingCart struct {
    	price    float64          // 商品价格
    	strategy DiscountStrategy // 当前使用的折扣策略
    }
    
    // NewShoppingCart 创建购物车
    func NewShoppingCart(price float64, strategy DiscountStrategy) *ShoppingCart {
    	return &ShoppingCart{price: price, strategy: strategy}
    }
    
    // SetStrategy 设置新的折扣策略
    func (c *ShoppingCart) SetStrategy(strategy DiscountStrategy) {
    	c.strategy = strategy
    }
    
    // CalculateFinalPrice 计算最终价格
    func (c *ShoppingCart) CalculateFinalPrice() float64 {
    	return c.strategy.applyDiscount(c.price)
    }
    
    // Main 函数
    func main() {
    	// 创建一个购物车,初始价格为100
    	cart := NewShoppingCart(100, &FullReductionStrategy{threshold: 80, reduction: 20})
    	fmt.Printf("最终价格(满减策略): %.2f\n", cart.CalculateFinalPrice()) // 应用满减策略
    
    	// 更改策略为百分比折扣
    	cart.SetStrategy(&PercentageDiscountStrategy{percentage: 10})
    	fmt.Printf("最终价格(折扣策略): %.2f\n", cart.CalculateFinalPrice()) // 应用折扣策略
    
    	// 更改策略为赠品
    	cart.SetStrategy(&GiftStrategy{giftValue: 5})
    	fmt.Printf("最终价格(赠品策略): %.2f\n", cart.CalculateFinalPrice()) // 赠品策略
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    最终价格(满减策略): 80.00
    最终价格(折扣策略): 90.00
    最终价格(赠品策略): 100.00
    

    说明

    • DiscountStrategy​ 接口定义了折扣策略的行为,包括 applyDiscount()​ 方法用于计算折扣后的价格。
    • FullReductionStrategy​、PercentageDiscountStrategy​ 和 GiftStrategy​ 是具体的折扣策略,实现了 DiscountStrategy​ 接口。
    • ShoppingCart​ 结构代表购物车,包含商品价格和当前使用的折扣策略,提供方法以设置策略和计算最终价格。
    • 在主函数中,创建购物车并依次使用不同的折扣策略进行价格计算,展示了策略模式的应用,使得可以灵活选择和更改折扣策略。
  21. 模板方法-go

    以下是一个在 Go 中实现模板方法模式的简易代码示例,使用 OrderProcessingTemplate​ 类来定义订单处理的模板方法,不同类型的订单(如虚拟商品、实物商品)可以复用通用流程并在特定步骤进行自定义。

    package main
    
    import (
    	"fmt"
    )
    
    // OrderProcessingTemplate 订单处理模板
    type OrderProcessingTemplate struct{}
    
    // Process 定义订单处理的模板方法
    func (t *OrderProcessingTemplate) Process() {
    	t.validateOrder()
    	t.prepareOrder()
    	t.processPayment()
    	t.shipOrder()
    }
    
    // ValidateOrder 验证订单
    func (t *OrderProcessingTemplate) validateOrder() {
    	fmt.Println("验证订单...")
    }
    
    // PrepareOrder 准备订单,留给子类实现
    func (t *OrderProcessingTemplate) prepareOrder() {
    	fmt.Println("准备订单...")
    }
    
    // ProcessPayment 处理支付
    func (t *OrderProcessingTemplate) processPayment() {
    	fmt.Println("处理支付...")
    }
    
    // ShipOrder 发货,留给子类实现
    func (t *OrderProcessingTemplate) shipOrder() {
    	fmt.Println("发货...")
    }
    
    // VirtualProductOrder 虚拟商品订单
    type VirtualProductOrder struct {
    	OrderProcessingTemplate
    }
    
    // PrepareOrder 实现虚拟商品订单的准备逻辑
    func (v *VirtualProductOrder) prepareOrder() {
    	fmt.Println("准备虚拟商品...")
    }
    
    // ShipOrder 实现虚拟商品订单的发货逻辑
    func (v *VirtualProductOrder) shipOrder() {
    	fmt.Println("虚拟商品通过电子邮件发送...")
    }
    
    // PhysicalProductOrder 实物商品订单
    type PhysicalProductOrder struct {
    	OrderProcessingTemplate
    }
    
    // PrepareOrder 实现实物商品订单的准备逻辑
    func (p *PhysicalProductOrder) prepareOrder() {
    	fmt.Println("准备实物商品...")
    }
    
    // ShipOrder 实现实物商品订单的发货逻辑
    func (p *PhysicalProductOrder) shipOrder() {
    	fmt.Println("实物商品通过快递发货...")
    }
    
    // Main 函数
    func main() {
    	// 处理虚拟商品订单
    	virtualOrder := &VirtualProductOrder{}
    	fmt.Println("处理虚拟商品订单:")
    	virtualOrder.Process()
    	fmt.Println()
    
    	// 处理实物商品订单
    	physicalOrder := &PhysicalProductOrder{}
    	fmt.Println("处理实物商品订单:")
    	physicalOrder.Process()
    }
    

    输出结果

    运行该代码,将会输出以下内容:

    处理虚拟商品订单:
    验证订单...
    准备虚拟商品...
    处理支付...
    虚拟商品通过电子邮件发送...
    
    处理实物商品订单:
    验证订单...
    准备实物商品...
    处理支付...
    实物商品通过快递发货...
    

    说明

    • OrderProcessingTemplate​ 定义了一个模板方法 Process​,其中包含订单处理的通用流程,涉及验证订单、准备订单、处理支付和发货等步骤。
    • prepareOrder()​ 和 shipOrder()​ 方法在模板中被定义为留给子类实现的抽象方法,以便在不同类型的订单中进行自定义。
    • VirtualProductOrder​ 和 PhysicalProductOrder​ 是具体的订单类型,分别实现了订单的准备和发货逻辑。
    • 在主函数中,创建虚拟商品订单和实物商品订单的实例,并调用 Process​ 方法进行订单处理,展示了模板方法的使用,使得可以复用通用的处理逻辑并在特定步骤自定义。
  22. 访问者-go

    以下是一个在 Go 中实现访问者模式的简易代码示例,使用 ReportVisitor​ 类来访问订单和客户信息,执行不同的统计分析逻辑。

    package main
    
    import "fmt"
    
    // Visitable 接口
    type Visitable interface {
    	Accept(visitor Visitor)
    }
    
    // Visitor 接口
    type Visitor interface {
    	visitOrder(order *Order)
    	visitCustomer(customer *Customer)
    }
    
    // Order 订单结构体
    type Order struct {
    	ID     int
    	Amount float64
    }
    
    // Accept 方法接受访问者
    func (o *Order) Accept(visitor Visitor) {
    	visitor.visitOrder(o)
    }
    
    // Customer 客户结构体
    type Customer struct {
    	ID   int
    	Name string
    }
    
    // Accept 方法接受访问者
    func (c *Customer) Accept(visitor Visitor) {
    	visitor.visitCustomer(c)
    }
    
    // ReportVisitor 实现 Visitor 接口
    type ReportVisitor struct {
    	TotalAmount   float64
    	CustomerCount int
    }
    
    // visitOrder 访问订单
    func (v *ReportVisitor) visitOrder(order *Order) {
    	v.TotalAmount += order.Amount
    	fmt.Printf("访问订单 ID: %d, 金额: %.2f\n", order.ID, order.Amount)
    }
    
    // visitCustomer 访问客户
    func (v *ReportVisitor) visitCustomer(customer *Customer) {
    	v.CustomerCount++
    	fmt.Printf("访问客户 ID: %d, 名称: %s\n", customer.ID, customer.Name)
    }
    
    // Main 函数
    func main() {
    	// 创建订单和客户
    	orders := []*Order{
    		{ID: 1, Amount: 100.50},
    		{ID: 2, Amount: 200.75},
    	}
    
    	customers := []*Customer{
    		{ID: 1, Name: "Alice"},
    		{ID: 2, Name: "Bob"},
    	}
    
    	// 创建报告访问者
    	reportVisitor := &ReportVisitor{}
    
    	// 访问订单
    	for _, order := range orders {
    		order.Accept(reportVisitor)
    	}
    
    	// 访问客户
    	for _, customer := range customers {
    		customer.Accept(reportVisitor)
    	}
    
    	// 输出统计结果
    	fmt.Printf("总订单金额: %.2f\n", reportVisitor.TotalAmount)
    	fmt.Printf("客户数量: %d\n", reportVisitor.CustomerCount)
    }
    

    输出结果

    运行该代码将会输出以下内容:

    访问订单 ID: 1, 金额: 100.50
    访问订单 ID: 2, 金额: 200.75
    访问客户 ID: 1, 名称: Alice
    访问客户 ID: 2, 名称: Bob
    总订单金额: 301.25
    客户数量: 2
    

    说明

    • Visitable​ 接口定义了接受访问者的方法 Accept​,用于让访问者访问对象。
    • Visitor​ 接口包含两个方法:visitOrder​ 和 visitCustomer​,分别用于访问订单和客户。
    • Order​ 和 Customer​ 结构体实现了 Visitable​ 接口,并在 Accept​ 方法中调用访问者的对应方法。
    • ReportVisitor​ 实现了 Visitor​ 接口,包含了统计总金额和客户数量的逻辑。
    • 在主函数中,创建了一些订单和客户的实例,并通过 ReportVisitor​ 对其进行访问,最终输出统计结果。
    • 这种设计模式的好处在于能够通过扩展访问者的方式,轻松地为不同类型的数据添加新的操作,而无需修改数据结构本身。
  • 待分类

    用户发帖时如果不填标签,则默认加上“待分类”。这样做是为了减少用户发帖的负担,同时也减少运营维护的工作量。具有帖子更新权限的用户可以帮助社区进行帖子整理,让大家可以更方便地找到所需内容。这里是关于这样设计的一些思考,欢迎讨论。

    2 引用 • -284 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...