登录
首页 >  Golang >  Go教程

Golang工厂加适配器模式详解

时间:2026-03-14 13:48:32 372浏览 收藏

本文深入探讨了如何在Go语言中巧妙结合工厂模式与适配器模式,解决异构日志组件(如zap、文件写入器、全局函数等)的统一接入难题:通过定义简洁的Logger接口确立契约,用结构体+方法实现各类适配器完成接口“翻译”,再由配置驱动的NewLogger工厂函数封装创建逻辑,彻底解耦调用方与具体实现——既规避了Go无类继承的限制,又充分发挥了接口、结构体和函数值作为一等公民的表达力,让老旧系统、第三方库与新架构无缝兼容,轻量、灵活且真正落地。

如何使用Golang实现工厂+适配器模式_创建对象并兼容接口

用 Go 实现工厂 + 适配器模式,核心是解耦对象创建逻辑与具体类型,同时让不兼容的接口“变相”符合统一契约。Go 没有类和继承,但靠接口(interface)+ 结构体(struct)+ 函数值,完全可以达成相同设计意图。

定义统一行为接口

先确定对外暴露的抽象能力——比如一个通用的 Logger 接口:

type Logger interface {
    Log(msg string)
}

所有日志实现都必须满足这个契约,后续才能被统一使用。

编写不同日志实现(适配目标)

现实里你可能已有第三方日志库(如 zap.Logger)或旧系统模块(如自定义 FileWriter),它们类型不同、方法名不同、参数也不同。这时就需要适配器:

  • ZapLoggerAdapter:包装 zap.Logger,把 Info() 映射为 Log()
  • FileWriterAdapter:把 WriteLine(string) 封装成 Log(string)
type ZapLoggerAdapter struct {
    logger *zap.Logger
}
func (a *ZapLoggerAdapter) Log(msg string) {
    a.logger.Info(msg)
}

type FileWriterAdapter struct {
    file *os.File
}
func (a *FileWriterAdapter) Log(msg string) {
    a.file.WriteString(msg + "\n")
}

用工厂封装创建逻辑

避免调用方感知底层类型差异,提供一个配置驱动的工厂函数:

type LoggerType string
const (
    ConsoleLogger LoggerType = "console"
    FileLogger    LoggerType = "file"
    ZapLogger     LoggerType = "zap"
)

func NewLogger(t LoggerType, cfg interface{}) (Logger, error) {
    switch t {
    case ConsoleLogger:
        return &ConsoleLoggerImpl{}, nil
    case FileLogger:
        if path, ok := cfg.(string); ok {
            f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
            if err != nil {
                return nil, err
            }
            return &FileWriterAdapter{file: f}, nil
        }
    case ZapLogger:
        z, err := zap.NewDevelopment()
        if err != nil {
            return nil, err
        }
        return &ZapLoggerAdapter{logger: z}, nil
    }
    return nil, fmt.Errorf("unknown logger type: %s", t)
}

调用时只需传入类型和配置,完全不关心内部结构是否带 zapos.File

logger, _ := NewLogger(FileLogger, "/tmp/app.log")
logger.Log("service started") // 统一调用

延伸:支持运行时动态适配(可选增强)

如果某些老模块只提供函数而非结构体(比如一个全局 func PrintToDB(string)),也可适配:

type FuncLoggerAdapter struct {
    fn func(string)
}
func (a *FuncLoggerAdapter) Log(msg string) {
    a.fn(msg)
}

// 工厂中支持:
case "db":
    return &FuncLoggerAdapter{fn: PrintToDB}, nil

Go 的函数是一等公民,这种轻量适配非常自然,无需额外 wrapper 类。

不复杂但容易忽略:适配器本身不新增功能,只做“翻译”;工厂不持有实例状态,保持无副作用。两者配合,就能在不改旧代码的前提下,让新系统平滑接入各种异构组件。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>