深入 Go 工厂模式:从简单工厂到支付系统实战

什么是工厂模式?

工厂模式是一种创建型设计模式,将对象的创建逻辑封装在“工厂”中,客户端无需关心具体实现。它的核心是创建与使用的分离,提高代码灵活性和可维护性。

工厂模式包括:

  • 简单工厂:通过一个工厂根据参数创建对象。
  • 工厂方法:定义工厂接口,由子类实现创建逻辑。
  • 抽象工厂:创建一组相关对象的工厂。

核心要素

  • 产品接口
  • 具体产品
  • 工厂
  • 客户端

适用场景

  • 根据条件创建不同对象(如支付方式)。
  • 对象创建复杂(如需要配置)。
  • 统一管理相关对象的创建。

为什么在 Go 中使用工厂模式?

Go 语言通过接口和结构体实现工厂模式,适用于:

  • 支付系统:动态创建微信、支付宝支付对象。
  • 数据库驱动:选择 MySQL、PostgreSQL 驱动。
  • 消息队列:创建 Kafka、RabbitMQ 客户端。

本文通过一个支付系统的例子,展示工厂模式在 Go 中的实现。

简单工厂实现

简单工厂通过一个函数根据参数创建支付对象,适合小型系统。

代码实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package payment

import (
    "errors"
    "fmt"
)

// Payment 接口,定义支付行为
type Payment interface {
    Process(amount float64) (string, error) // 处理支付,返回交易ID
}

// WeChatPay 微信支付实现
type WeChatPay struct{}

func (w *WeChatPay) Process(amount float64) (string, error) {
    if amount <= 0 {
        return "", errors.New("invalid amount")
    }
    transactionID := fmt.Sprintf("WX-%d", time.Now().UnixNano())
    return transactionID, nil
}

// AliPay 支付宝实现
type AliPay struct{}

func (a *AliPay) Process(amount float64) (string, error) {
    if amount <= 0 {
        return "", errors.New("invalid amount")
    }
    transactionID := fmt.Sprintf("ALI-%d", time.Now().UnixNano())
    return transactionID, nil
}

// PaymentType 支付类型枚举
type PaymentType string

const (
    WeChat PaymentType = "wechat"
    AliPay PaymentType = "alipay"
)

// PaymentFactory 简单工厂函数
func PaymentFactory(paymentType PaymentType) (Payment, error) {
    switch paymentType {
    case WeChat:
        return &WeChatPay{}, nil
    case AliPay:
        return &AliPay{}, nil
    default:
        return nil, fmt.Errorf("unsupported payment type: %s", paymentType)
    }
}

使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
    "fmt"
    "yourmodule/payment"
)

func main() {
    wechatPay, err := payment.PaymentFactory(payment.WeChat)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    transactionID, err := wechatPay.Process(100.50)
    if err != nil {
        fmt.Println("Payment failed:", err)
        return
    }
    fmt.Println("WeChat Payment Success, Transaction ID:", transactionID)

    aliPay, err := payment.PaymentFactory(payment.AliPay)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    transactionID, err = aliPay.Process(200.75)
    if err != nil {
        fmt.Println("Payment failed:", err)
        return
    }
    fmt.Println("AliPay Payment Success, Transaction ID:", transactionID)
}

讲解

  • PaymentFactory根据PaymentType创建支付对象。
  • 客户端通过工厂获取对象,无需直接实例化。
  • 局限性:扩展需要修改switch语句。

工厂方法实现

工厂方法通过接口分散创建逻辑,每个支付方式对应一个工厂,增强扩展性。

代码实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package payment

import (
    "errors"
    "fmt"
    "time"
)

// Payment 接口,定义支付行为
type Payment interface {
    Process(amount float64) (string, error)
}

// WeChatPay 微信支付
type WeChatPay struct{}

func (w *WeChatPay) Process(amount float64) (string, error) {
    if amount <= 0 {
        return "", errors.New("invalid amount")
    }
    return fmt.Sprintf("WX-%d", time.Now().UnixNano()), nil
}

// AliPay 支付宝
type AliPay struct{}

func (a *AliPay) Process(amount float64) (string, error) {
    if amount <= 0 {
        return "", errors.New("invalid amount")
    }
    return fmt.Sprintf("ALI-%d", time.Now().UnixNano()), nil
}

// PaymentFactory 工厂接口
type PaymentFactory interface {
    CreatePayment() Payment
}

// WeChatPaymentFactory 微信支付工厂
type WeChatPaymentFactory struct{}

func (w *WeChatPaymentFactory) CreatePayment() Payment {
    return &WeChatPay{}
}

// AliPayFactory 支付宝工厂
type AliPayFactory struct{}

func (a *AliPayFactory) CreatePayment() Payment {
    return &AliPay{}
}

使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
    "fmt"
    "yourmodule/payment"
)

func main() {
    wechatFactory := &payment.WeChatPaymentFactory{}
    wechatPay := wechatFactory.CreatePayment()
    transactionID, err := wechatPay.Process(100.50)
    if err != nil {
        fmt.Println("Payment failed:", err)
        return
    }
    fmt.Println("WeChat Payment Success, Transaction ID:", transactionID)

    aliFactory := &payment.AliPayFactory{}
    aliPay := aliFactory.CreatePayment()
    transactionID, err = aliPay.Process(200.75)
    if err != nil {
        fmt.Println("Payment failed:", err)
        return
    }
    fmt.Println("AliPay Payment Success, Transaction ID:", transactionID)
}

讲解

  • 每个支付方式有自己的工厂,符合“开闭原则”。
  • 优势:扩展只需添加新工厂,无需修改现有代码。

抽象工厂实现

抽象工厂创建一组相关对象(如支付处理器和验证器),适合复杂场景。

代码实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package payment

import (
    "errors"
    "fmt"
    "sync"
    "time"
)

// PaymentProcessor 处理支付
type PaymentProcessor interface {
    Process(amount float64) (string, error)
}

// PaymentValidator 验证支付状态
type PaymentValidator interface {
    Validate(transactionID string) (bool, error)
}

// WeChatProcessor 微信支付处理器
type WeChatProcessor struct {
    mu sync.Mutex
    transactions map[string]float64
}

func (w *WeChatProcessor) Process(amount float64) (string, error) {
    if amount <= 0 {
        return "", errors.New("invalid amount")
    }
    w.mu.Lock()
    defer w.mu.Unlock()
    transactionID := fmt.Sprintf("WX-%d", time.Now().UnixNano())
    w.transactions[transactionID] = amount
    return transactionID, nil
}

func (w *WeChatProcessor) Validate(transactionID string) (bool, error) {
    w.mu.Lock()
    defer w.mu.Unlock()
    _, exists := w.transactions[transactionID]
    return exists, nil
}

// AliPayProcessor 支付宝处理器
type AliPayProcessor struct {
    mu sync.Mutex
    transactions map[string]float64
}

func (a *AliPayProcessor) Process(amount float64) (string, error) {
    if amount <= 0 {
        return "", errors.New("invalid amount")
    }
    a.mu.Lock()
    defer a.mu.Unlock()
    transactionID := fmt.Sprintf("ALI-%d", time.Now().UnixNano())
    a.transactions[transactionID] = amount
    return transactionID, nil
}

func (a *AliPayProcessor) Validate(transactionID string) (bool, error) {
    a.mu.Lock()
    defer a.mu.Unlock()
    _, exists := a.transactions[transactionID]
    return exists, nil
}

// PaymentAbstractFactory 抽象工厂接口
type PaymentAbstractFactory interface {
    CreateProcessor() PaymentProcessor
    CreateValidator() PaymentValidator
}

// WeChatAbstractFactory 微信支付抽象工厂
type WeChatAbstractFactory struct{}

func (w *WeChatAbstractFactory) CreateProcessor() PaymentProcessor {
    return &WeChatProcessor{transactions: make(map[string]float64)}
}

func (w *WeChatAbstractFactory) CreateValidator() PaymentValidator {
    return &WeChatProcessor{transactions: make(map[string]float64)}
}

// AliPayAbstractFactory 支付宝抽象工厂
type AliPayAbstractFactory struct{}

func (a *AliPayAbstractFactory) CreateProcessor() PaymentProcessor {
    return &AliPayProcessor{transactions: make(map[string]float64)}
}

func (a *AliPayAbstractFactory) CreateValidator() PaymentValidator {
    return &AliPayProcessor{transactions: make(map[string]float64)}
}

使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
    "fmt"
    "yourmodule/payment"
)

func main() {
    wechatFactory := &payment.WeChatAbstractFactory{}
    processor := wechatFactory.CreateProcessor()
    validator := wechatFactory.CreateValidator()

    transactionID, err := processor.Process(100.50)
    if err != nil {
        fmt.Println("Payment failed:", err)
        return
    }
    fmt.Println("WeChat Payment Success, Transaction ID:", transactionID)

    valid, err := validator.Validate(transactionID)
    if err != nil {
        fmt.Println("Validation failed:", err)
        return
    }
    fmt.Println("Transaction Valid:", valid)

    aliFactory := &payment.AliPayAbstractFactory{}
    processor = aliFactory.CreateProcessor()
    transactionID, err = processor.Process(200.75)
    if err != nil {
        fmt.Println("Payment failed:", err)
        return
    }
    fmt.Println("AliPay Payment Success, Transaction ID:", transactionID)
}

讲解

  • 抽象工厂创建处理器和验证器,管理相关对象。
  • 使用sync.Mutex确保并发安全。
  • 优势:适合复杂系统,统一管理对象族。

常见问题

  1. 简单工厂和工厂方法区别? 简单工厂集中创建逻辑,扩展需修改代码;工厂方法分散逻辑,扩展性更好。

  2. Go 中需要工厂模式吗? 在封装创建逻辑、支持扩展的场景中,工厂模式很有用。

  3. 如何处理并发? 使用sync.Mutexsync.Once确保线程安全。

总结

工厂模式在 Go 中通过接口和结构体实现,适合支付系统等场景。本文展示了简单工厂、工厂方法和抽象工厂的实现,以及在支付系统中的应用。希望这篇文章帮助您掌握工厂模式!

欢迎留言:分享您在 Go 项目中使用工厂模式的经验!

评论 0