本文以电商系统为例讲述设计模式在项目中的应用
在面试时经常会被问到项目中设计模式的使用情况,以及自己在开发时也会纠结如何在项目正确使用设计模式,今天就以大家都熟知的电商系统为例,简述一下系统中如何使用常见设计模式的场景。并用Go语言实现相应的示例代码。

1. 工厂模式 - 创建不同支付方式

package main

import "fmt"

// PaymentMethod 支付接口
type PaymentMethod interface {
    Pay(amount float64) string
}

// 具体支付方式
type Alipay struct{}
func (a *Alipay) Pay(amount float64) string {
    return fmt.Sprintf("支付宝支付: %.2f 元", amount)
}

type WechatPay struct{}
func (w *WechatPay) Pay(amount float64) string {
    return fmt.Sprintf("微信支付: %.2f 元", amount)
}

type CreditCard struct{}
func (c *CreditCard) Pay(amount float64) string {
    return fmt.Sprintf("信用卡支付: %.2f 元", amount)
}

// PaymentMethodType 支付类型
type PaymentMethodType int

const (
    AlipayType PaymentMethodType = iota
    WechatPayType
    CreditCardType
)

// PaymentFactory 支付工厂
func PaymentFactory(methodType PaymentMethodType) PaymentMethod {
    switch methodType {
    case AlipayType:
        return &Alipay{}
    case WechatPayType:
        return &WechatPay{}
    case CreditCardType:
        return &CreditCard{}
    default:
        return nil
    }
}

func main() {
    // 使用工厂创建支付方式
    payment := PaymentFactory(AlipayType)
    fmt.Println(payment.Pay(100.50))
    
    payment = PaymentFactory(WechatPayType)
    fmt.Println(payment.Pay(200.00))
}

2. 单例模式 - 配置管理器

package main

import (
    "fmt"
    "sync"
)

// Config 配置结构
type Config struct {
    DatabaseURL string
    Port        string
    APIKey      string
}

var (
    instance *Config
    once     sync.Once
)

// GetConfig 获取配置单例
func GetConfig() *Config {
    once.Do(func() {
        instance = &Config{
            DatabaseURL: "localhost:3306/ecommerce",
            Port:        "8080",
            APIKey:      "abc123xyz",
        }
    })
    return instance
}

func main() {
    config1 := GetConfig()
    config2 := GetConfig()
    
    fmt.Println("配置相同:", config1 == config2)
    fmt.Printf("数据库地址: %s\n", config1.DatabaseURL)
}

3. 观察者模式 - 订单状态通知

package main

import "fmt"

// Observer 观察者接口
type Observer interface {
    Update(orderID string, status string)
}

// Subject 主题接口
type Subject interface {
    Register(observer Observer)
    Remove(observer Observer)
    NotifyAll()
}

// Order 订单主题
type Order struct {
    observers []Observer
    ID        string
    Status    string
}

func (o *Order) Register(observer Observer) {
    o.observers = append(o.observers, observer)
}

func (o *Order) Remove(observer Observer) {
    for i, obs := range o.observers {
        if obs == observer {
            o.observers = append(o.observers[:i], o.observers[i+1:]...)
            break
        }
    }
}

func (o *Order) NotifyAll() {
    for _, observer := range o.observers {
        observer.Update(o.ID, o.Status)
    }
}

func (o *Order) UpdateStatus(status string) {
    o.Status = status
    o.NotifyAll()
}

// 具体观察者
type CustomerNotifier struct{}
func (c *CustomerNotifier) Update(orderID string, status string) {
    fmt.Printf("客户通知: 订单 %s 状态更新为 %s\n", orderID, status)
}

type LogisticsNotifier struct{}
func (l *LogisticsNotifier) Update(orderID string, status string) {
    fmt.Printf("物流通知: 订单 %s 状态更新为 %s\n", orderID, status)
}

func main() {
    order := &Order{ID: "ORD12345"}
    
    // 注册观察者
    order.Register(&CustomerNotifier{})
    order.Register(&LogisticsNotifier{})
    
    // 更新状态并通知
    order.UpdateStatus("已付款")
    order.UpdateStatus("已发货")
}

4. 策略模式 - 折扣计算

package main

import "fmt"

// DiscountStrategy 折扣策略接口
type DiscountStrategy interface {
    Calculate(price float64) float64
}

// 具体策略
type NoDiscount struct{}
func (n *NoDiscount) Calculate(price float64) float64 {
    return price
}

type PercentageDiscount struct {
    percentage float64
}
func (p *PercentageDiscount) Calculate(price float64) float64 {
    return price * (1 - p.percentage/100)
}

type FixedDiscount struct {
    amount float64
}
func (f *FixedDiscount) Calculate(price float64) float64 {
    result := price - f.amount
    if result < 0 {
        return 0
    }
    return result
}

// DiscountContext 折扣上下文
type DiscountContext struct {
    strategy DiscountStrategy
}

func (d *DiscountContext) SetStrategy(strategy DiscountStrategy) {
    d.strategy = strategy
}

func (d *DiscountContext) ApplyDiscount(price float64) float64 {
    return d.strategy.Calculate(price)
}

func main() {
    context := &DiscountContext{}
    
    // 无折扣
    context.SetStrategy(&NoDiscount{})
    fmt.Printf("无折扣: %.2f\n", context.ApplyDiscount(100))
    
    // 8折
    context.SetStrategy(&PercentageDiscount{percentage: 20})
    fmt.Printf("8折: %.2f\n", context.ApplyDiscount(100))
    
    // 满减
    context.SetStrategy(&FixedDiscount{amount: 30})
    fmt.Printf("满减30: %.2f\n", context.ApplyDiscount(100))
}

5. 装饰器模式 - 商品添加功能

package main

import "fmt"

// Product 商品接口
type Product interface {
    GetDescription() string
    GetPrice() float64
}

// BasicProduct 基础商品
type BasicProduct struct {
    name  string
    price float64
}

func (b *BasicProduct) GetDescription() string {
    return b.name
}

func (b *BasicProduct) GetPrice() float64 {
    return b.price
}

// ProductDecorator 商品装饰器
type ProductDecorator struct {
    product Product
}

func (p *ProductDecorator) GetDescription() string {
    return p.product.GetDescription()
}

func (p *ProductDecorator) GetPrice() float64 {
    return p.product.GetPrice()
}

// 具体装饰器
type GiftWrapDecorator struct {
    ProductDecorator
}

func (g *GiftWrapDecorator) GetDescription() string {
    return g.product.GetDescription() + " + 礼品包装"
}

func (g *GiftWrapDecorator) GetPrice() float64 {
    return g.product.GetPrice() + 5.0
}

type ExpressDeliveryDecorator struct {
    ProductDecorator
}

func (e *ExpressDeliveryDecorator) GetDescription() string {
    return e.product.GetDescription() + " + 快递配送"
}

func (e *ExpressDeliveryDecorator) GetPrice() float64 {
    return e.product.GetPrice() + 15.0
}

func main() {
    // 基础商品
    product := &BasicProduct{name: "手机", price: 2999.0}
    fmt.Printf("%s, 价格: %.2f\n", product.GetDescription(), product.GetPrice())
    
    // 添加礼品包装
    giftWrapped := &GiftWrapDecorator{ProductDecorator{product}}
    fmt.Printf("%s, 价格: %.2f\n", giftWrapped.GetDescription(), giftWrapped.GetPrice())
    
    // 添加快递配送
    expressDelivered := &ExpressDeliveryDecorator{ProductDecorator{giftWrapped}}
    fmt.Printf("%s, 价格: %.2f\n", expressDelivered.GetDescription(), expressDelivered.GetPrice())
}

6. 仓储模式 - 数据访问层

package main

import "fmt"

// User 用户模型
type User struct {
    ID    int
    Name  string
    Email string
}

// UserRepository 用户仓储接口
type UserRepository interface {
    FindByID(id int) (*User, error)
    Save(user *User) error
    Delete(id int) error
}

// InMemoryUserRepository 内存用户仓储
type InMemoryUserRepository struct {
    users map[int]*User
}

func NewInMemoryUserRepository() *InMemoryUserRepository {
    return &InMemoryUserRepository{
        users: make(map[int]*User),
    }
}

func (r *InMemoryUserRepository) FindByID(id int) (*User, error) {
    user, exists := r.users[id]
    if !exists {
        return nil, fmt.Errorf("用户不存在")
    }
    return user, nil
}

func (r *InMemoryUserRepository) Save(user *User) error {
    r.users[user.ID] = user
    return nil
}

func (r *InMemoryUserRepository) Delete(id int) error {
    delete(r.users, id)
    return nil
}

func main() {
    repo := NewInMemoryUserRepository()
    
    // 保存用户
    user := &User{ID: 1, Name: "张三", Email: "zhangsan@example.com"}
    repo.Save(user)
    
    // 查找用户
    foundUser, _ := repo.FindByID(1)
    fmt.Printf("找到用户: %s, 邮箱: %s\n", foundUser.Name, foundUser.Email)
}

7. 责任链模式 - 订单处理流程

package main

import "fmt"

// Order 订单
type Order struct {
    ID          string
    Items       []string
    TotalAmount float64
    IsVerified  bool
    IsPaid      bool
    IsShipped   bool
}

// OrderHandler 订单处理接口
type OrderHandler interface {
    SetNext(handler OrderHandler)
    Handle(order *Order) error
}

// 具体处理者
type VerificationHandler struct {
    next OrderHandler
}

func (v *VerificationHandler) SetNext(handler OrderHandler) {
    v.next = handler
}

func (v *VerificationHandler) Handle(order *Order) error {
    fmt.Println("验证订单中...")
    order.IsVerified = true
    fmt.Println("订单验证完成")
    
    if v.next != nil {
        return v.next.Handle(order)
    }
    return nil
}

type PaymentHandler struct {
    next OrderHandler
}

func (p *PaymentHandler) SetNext(handler OrderHandler) {
    p.next = handler
}

func (p *PaymentHandler) Handle(order *Order) error {
    fmt.Println("处理支付中...")
    order.IsPaid = true
    fmt.Println("支付处理完成")
    
    if p.next != nil {
        return p.next.Handle(order)
    }
    return nil
}

type ShippingHandler struct {
    next OrderHandler
}

func (s *ShippingHandler) SetNext(handler OrderHandler) {
    s.next = handler
}

func (s *ShippingHandler) Handle(order *Order) error {
    fmt.Println("处理发货中...")
    order.IsShipped = true
    fmt.Println("发货处理完成")
    
    if s.next != nil {
        return s.next.Handle(order)
    }
    return nil
}

func main() {
    // 创建处理链
    verification := &VerificationHandler{}
    payment := &PaymentHandler{}
    shipping := &ShippingHandler{}
    
    verification.SetNext(payment)
    payment.SetNext(shipping)
    
    // 创建订单
    order := &Order{
        ID:          "ORD67890",
        Items:       []string{"商品A", "商品B"},
        TotalAmount: 150.50,
    }
    
    // 处理订单
    verification.Handle(order)
    
    fmt.Printf("订单状态: 验证=%t, 支付=%t, 发货=%t\n", 
        order.IsVerified, order.IsPaid, order.IsShipped)
}

这些示例展示了电商项目中常用的设计模式实现。每种模式都解决了特定的设计问题:

  • 工厂模式:创建对象的逻辑封装,便于扩展新的支付方式
  • 单例模式:确保配置信息全局唯一
  • 观察者模式:实现订单状态变化的通知机制
  • 策略模式:灵活切换不同的折扣计算算法
  • 装饰器模式:动态添加商品额外功能
  • 仓储模式:抽象数据访问层,便于切换数据源
  • 责任链模式:处理订单流程中的多个步骤

这些模式可以帮助构建灵活、可维护和可扩展的电商系统架构。
希望这些设计模式使用场景举例,可以给大家提供使用和设计灵感。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐