Provider模式:软件架构中的“供应商“设计哲学

文章目录

  • Provider模式:软件架构中的“供应商“设计哲学
    • 什么是Provider模式?
    • 经典应用场景
      • 1. 配置管理Provider
      • 2. 数据访问Provider
      • 4. 消息队列Provider
    • Provider模式的优势
      • 1. 解耦合
    • 实际项目中的应用
    • Provider模式的最佳实践
      • 1. 命名约定
      • 2. 接口设计原则
      • 3. 错误处理
    • 总结

Provider模式:软件架构中的“供应商“设计哲学

在软件开发中,你是否遇到过这样的困扰:代码与特定的数据源、配置来源或服务紧密耦合,导致测试困难、扩展性差?Provider 模式正是解决这类问题的经典设计模式。

什么是Provider模式?

Provider模式是一种创建型设计模式,它定义了一个统一的接口来"提供"某种资源或服务,而具体的提供方式由不同的实现类来决定

核心思想

  • 抽象供应:定义"提供什么",而不关心"如何提供"
  • 实现分离:将资源获取的逻辑与业务逻辑分离
  • 可替换性:不同环境可以使用不同的Provider实现

为什么叫Provider?
Provider 这个词来自英文"供应商"的概念:

现实世界:
餐厅(业务逻辑) <- 食材供应商(Provider) <- 不同来源(农场、批发市场、进口商)

软件世界:
应用程序(业务逻辑) <- ConfigProvider <- 不同来源(文件、数据库、配置中心)

经典应用场景

1. 配置管理Provider

// 配置提供者接口

type ConfigProvider interface {GetConfig(key string) (string, error)GetIntConfig(key string) (int, error)
}
// 文件配置提供者
type FileConfigProvider struct {filePath string
}func (p *FileConfigProvider) GetConfig(key string) (string, error) {// 从文件读取配置return readFromFile(p.filePath, key)
}

// 环境变量配置提供者

type EnvConfigProvider struct{}func (p *EnvConfigProvider) GetConfig(key string) (string, error) {return os.Getenv(key), nil
}

// 远程配置提供者

type RemoteConfigProvider struct {endpoint string
}func (p *RemoteConfigProvider) GetConfig(key string) (string, error) {// 从配置中心获取return fetchFromRemote(p.endpoint, key)
}

应用场景:
开发环境使用本地文件
测试环境使用环境变量
生产环境使用配置中心

2. 数据访问Provider

// 数据提供者接口
type DataProvider interface {GetUser(id string) (*User, error)SaveUser(user *User) error
}// MySQL数据提供者
type MySQLDataProvider struct {db *sql.DB
}// Redis数据提供者
type RedisDataProvider struct {client *redis.Client
}// 内存数据提供者(测试用)
type MemoryDataProvider struct {users map[string]*User
}
3. 认证Provider
// 认证提供者接口
type AuthProvider interface {Authenticate(token string) (*User, error)GenerateToken(user *User) (string, error)
}// JWT认证提供者
type JWTAuthProvider struct {secretKey string
}// OAuth认证提供者
type OAuthAuthProvider struct {clientID     stringclientSecret string
}// LDAP认证提供者
type LDAPAuthProvider struct {serverURL string
}

4. 消息队列Provider

// 消息提供者接口
type MessageProvider interface {Publish(topic string, message []byte) errorSubscribe(topic string, handler func([]byte)) error
}// Kafka提供者
type KafkaMessageProvider struct {brokers []string
}// RabbitMQ提供者
type RabbitMQMessageProvider struct {connectionURL string
}// 内存队列提供者(开发测试用)
type InMemoryMessageProvider struct {queues map[string][]chan []byte
}

Provider模式的优势

1. 解耦合

// 不好的设计:直接依赖具体实现
type UserService struct {mysqlDB *sql.DB  // 强依赖MySQL
}// 好的设计:依赖抽象
type UserService struct {dataProvider DataProvider  // 可以是任何实现
}
  1. 可测试性
func TestUserService_GetUser(t *testing.T) {// 使用Mock Provider进行测试mockProvider := &MockDataProvider{users: map[string]*User{"123": {ID: "123", Name: "Test User"},},}service := NewUserService(mockProvider)user, err := service.GetUser("123")assert.NoError(t, err)assert.Equal(t, "Test User", user.Name)
}
  1. 环境适配
func NewUserService(env string) *UserService {var provider DataProviderswitch env {case "development":provider = NewMemoryDataProvider()case "testing":provider = NewMockDataProvider()case "production":provider = NewMySQLDataProvider(prodDB)}return &UserService{dataProvider: provider}
}

实际项目中的应用

云服务Provider

// 对象存储Provider
type ObjectStorageProvider interface {Upload(key string, data []byte) errorDownload(key string) ([]byte, error)
}// AWS S3实现
type S3StorageProvider struct {client *s3.S3bucket string
}// 阿里云OSS实现
type OSSStorageProvider struct {client *oss.Clientbucket string
}// 腾讯云COS实现
type COSStorageProvider struct {client *cos.Clientbucket string
}

Provider模式的最佳实践

1. 命名约定

接口名:XxxProvider
实现名:具体技术 + XxxProvider
// ✅ 好的命名
type ConfigProvider interface {}
type FileConfigProvider struct {}
type RedisConfigProvider struct {}// ❌ 不好的命名
type Config interface {}
type FileConfig struct {}

2. 接口设计原则

// ✅ 职责单一
type ConfigProvider interface {GetConfig(key string) (string, error)
}type CacheProvider interface {Get(key string) (interface{}, error)Set(key string, value interface{}) error
}// ❌ 职责混乱
type Provider interface {GetConfig(key string) (string, error)CacheGet(key string) (interface{}, error)SendEmail(to, subject, body string) error
}

3. 错误处理

type DatabaseProvider interface {GetUser(id string) (*User, error)
}// 定义特定的错误类型
var (ErrUserNotFound = errors.New("user not found")ErrConnectionFailed = errors.New("database connection failed")
)

总结

Provider模式是现代软件架构中的重要设计模式,它通过抽象化资源提供方式,实现了:

  • 高内聚低耦合:业务逻辑与资源获取分离
  • 可测试性:易于编写单元测试
  • 可扩展性:新增Provider实现无需修改现有代码
  • 环境适配:不同环境使用不同的Provider

在实际项目中,无论是配置管理、数据访问、认证授权,还是第三方服务集成,Provider模式都能帮助我们构建更加灵活、可维护的系统架构。

记住:好的架构不是一开始就完美的,而是能够优雅地适应变化的。 Provider模式正是这种适应性的体现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/bicheng/88983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LTspic下载,帮助及演示电路

1.下载 LTspice是一款强大高效的免费SPICE仿真器软件、原理图采集和波形观测器&#xff0c;为改善模拟电路的仿真提供增强功能和模型。其原理图捕获图形界面使您能够探测原理图并生成仿真结果&#xff0c;这些结果可以通过内置波形查看器进一步观察分析。 链接&#xff1a; …

位置编码/绝对位置编码/相对位置编码/Rope原理+公式详细推导及代码实现

文章目录1. 位置编码概述1.1 为什么需要位置编码&#xff1f;2. 绝对位置编码 (Absolute Position Encoding)2.1 原理2.2 数学公式2.3 代码实现2.4 代码与公式的对应关系2.5 特性与优势2.6 可学习的绝对位置编码3. 相对位置编码 (Relative Position Encoding)3.1 原理3.2 数学公…

网络安全初级第一次作业

一&#xff0c;docker搭建和挂载vpm 1.安装 Docker apt-get install docker.io docker-compose 2.创建文件 mkdir /etc/docker.service.d vim /etc/docker.service.d/http-proxy.conf 3.改写文件配置 [Service] Environment"HTTP_PROXYhttp://192.168.10.103:7890…

交换类排序的C语言实现

交换类排序包括冒泡排序和快速排序两种。冒泡排序基本介绍冒泡排序是通过重复比较相邻元素并交换位置实现排序。其核心思想是每一轮遍历将未排序序列中的最大&#xff08;或最小&#xff09;元素"浮动"到正确位置&#xff0c;类似气泡上升。基本过程是从序列起始位置…

嵌入式 Linux开发环境构建之Source Insight 的安装和使用

目录 一、Source Insight 的安装 二、Source Insight 使用 一、Source Insight 的安装 这个软件是代码编辑和查看软件&#xff0c;打开开发板光盘软件&#xff0c;然后右键选择以管理员身份运行这个安装包。在弹出来的安装向导里面点击 next &#xff0c;如下图所示。这里选择…

【字节跳动】数据挖掘面试题0016:解释AUC的定义,它解决了什么问题,优缺点是什么,并说出工业界如何计算AUC。

文章大纲 AUC(Area Under the Curve)详解一、定义:AUC是什么?二、解决了什么问题?三、优缺点分析四、工业界大规模计算AUC的方法1. 标准计算(小数据)2. 工业级大规模计算方案3.工业界最佳实践4.工业界方案选型建议总结:AUC的本质AUC(Area Under the Curve)详解 一、…

Python后端项目之:我为什么使用pdm+uv

在试用了一段时间的uv和pdm之后&#xff0c;上个月(2025.06)开始&#xff0c;逐步把用了几年的poetry替换成了pdmuv&#xff08;pipx install pdm uv && pdm config use_uv true) ## 为什么poetry -> pdm: 1. 通过ssh连接到服务器并使用poetry shell激活虚拟环境之…

鸿蒙Next开发,配置Navigation的Route

1. 通过router_map.json配置文件进行 创建页面配置router_map.json {"routerMap": [{"name": "StateExamplePage","pageSourceFile": "src/main/ets/pages/state/StateExamplePage.ets","buildFunction": "P…

在 GitHub 上创建私有仓库

一、在 GitHub 上创建私有仓库打开 GitHub官网 并登录。点击右上角的 “” → 选择 “New repository”。填写以下内容&#xff1a; Repository name&#xff1a;仓库名称&#xff0c;例如 my-private-repo。Description&#xff1a;可选&#xff0c;仓库描述。Visibility&…

量产技巧之RK3588 Android12默认移除导航栏状态栏​

本文介绍使用源码编译默认去掉导航栏/状态栏方法,以触觉智能EVB3588开发板演示&#xff0c;Android12系统&#xff0c;搭载了瑞芯微RK3588芯片&#xff0c;该开发板是核心板加底板设计&#xff0c;音视频接口、通信接口等各类接口一应俱全&#xff0c;可帮助企业提高产品开发效…

Conda 安装与配置详解及常见问题解决

《Conda 安装与配置详解及常见问题解决》 安装 Conda 有两种主流方式&#xff0c;分别是安装 Miniconda&#xff08;轻量级&#xff09;和 Anaconda&#xff08;包含常用数据科学包&#xff09;。下面为你详细介绍安装步骤和注意要点。 一、安装 Miniconda&#xff08;推荐&a…

Linux ——lastb定时备份清理

lastb 命令显示的是系统中 /var/log/btmp 文件中的SSH 登录失败记录。你可以像处理 wtmp 那样&#xff0c;对 btmp 文件进行备份与清理。✅ 一、备份 lastb 数据cp /var/log/btmp /var/log/btmp.backup.$(date %F)会保存为如 /var/log/btmp.backup.2025-07-14✅ 二、清空 lastb…

自定义类型 - 联合体与枚举(百度笔试题算法优化)

目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.3 相同成员的结构体和联合体对比1.4 联合体大小的计算1.5 联合练习二、枚举类型2.1 枚举类型的声明2.2 枚举类型的优点总结一、联合体 1.1 联合体类型的声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成…

FS820R08A6P2LB——英飞凌高性能IGBT模块,驱动高效能源未来!

产品概述FS820R08A6P2LB 是英飞凌&#xff08;Infineon&#xff09;推出的一款高性能、高可靠性IGBT功率模块&#xff0c;采用先进的EconoDUAL™ 3封装&#xff0c;专为大功率工业应用设计。该模块集成了IGBT&#xff08;绝缘栅双极型晶体管&#xff09;和二极管&#xff0c;适…

python学智能算法(十八)|SVM基础概念-向量点积

引言 前序学习进程中&#xff0c;已经对向量的基础定义有所了解&#xff0c;已经知晓了向量的值和方向向量的定义&#xff0c;学习链接如下&#xff1a; 向量的值和方向 在此基础上&#xff0c;本文进一步学习向量点积。 向量点积 向量点积运算规则&#xff0c;我们在中学阶…

【windows办公小助手】比文档编辑器更好用的Notepad++轻量编辑器

Notepad 中文版软件下载&#xff1a;这个路径总是显示有百度无法下载&#xff0c;不推荐 更新&#xff1a;推荐下载路径 https://github.com/notepad-plus-plus/notepad-plus-plus/releases 参考博主&#xff1a;Notepad的安装与使用

2025年7月12日全国青少年信息素养大赛图形化(Scratch)编程小学高年级组复赛真题+答案解析

2025年7月12日全国青少年信息素养大赛图形化(Scratch)编程小学高年级组复赛真题+答案解析 选择题 题目一 运行如图所示的程序,舞台上一共会出现多少只小猫呢?( ) A. 5 B. 6 C. 7 D. 8 正确答案: B 答案解析: 程序中“当绿旗被点击”后,角色先移到指定位置,然后“重…

对于独热编码余弦相似度结果为0和词向量解决了词之间相似性问题的理解

文章目录深入理解简单案例结论词向量&#xff08;Word Embedding&#xff09;简介词向量如何解决相似性问题&#xff1f;简单案例&#xff1a;基于上下文的词向量训练总结对于独热表示的向量&#xff0c;如果采用余弦相似度计算向量间的相似度&#xff0c;可以明显的发现任意两…

数据结构·数状数组(BIT)

树状数组(Binary Index Tree) 英文名&#xff1a;使用二进制下标的树结构 理解&#xff1a;这个树实际上用数组来存&#xff0c;二进制下标就是将正常的下标拆为二进制来看。 求x的最低位1的函数lowbit&#xff08;x&#xff09; 假设x的二进制表示为x ...10000&#xff0c;…

uniapp video视频全屏播放后退出,页面字体变大,样式混乱问题

uniapp官方的说法是因为页面使用rpx&#xff0c;但是全屏和退出全屏自动计算屏幕尺寸不支持rpx&#xff0c;建议使用px。但是因为uniapp端的开发都是使用rpx作为屏幕尺寸计算参数&#xff0c;不可能因为video全屏播放功能就整个全部修改&#xff0c;工作量大&#xff0c;耗时耗…