Golang学习笔记_29——抽象工厂模式

Golang学习笔记_26------通道
Golang学习笔记_27------单例模式
Golang学习笔记_28------工厂方法模式


文章目录

    • 抽象工厂模式
      • 一、抽象工厂模式核心概念
        • [1. 解决的问题](#1. 解决的问题)
        • [2. 关键角色](#2. 关键角色)
        • [3. 类图](#3. 类图)
      • 二、模式特点
      • 三、适用场景
        • [1. 需要创建一组相关或依赖的对象](#1. 需要创建一组相关或依赖的对象)
        • [2. 系统需要独立于产品的创建、组合和表示](#2. 系统需要独立于产品的创建、组合和表示)
        • [3. 需要确保产品之间的兼容性](#3. 需要确保产品之间的兼容性)
        • [4. 需要动态切换产品族](#4. 需要动态切换产品族)
        • [5. 需要隐藏具体产品的实现细节](#5. 需要隐藏具体产品的实现细节)
      • [四、Go 语言代码示例](#四、Go 语言代码示例)
      • 五、与其他模式对比

抽象工厂模式

抽象工厂模式(Abstract Factory)是一种创建型设计模式,用于创建一系列相关或依赖对象的家族,而无需指定它们的具体类。

一、抽象工厂模式核心概念

1. 解决的问题
  • 当需要创建多个相互关联或依赖的对象(例如同一主题的 UI 按钮、文本框、下拉框),且希望系统独立于这些对象的创建方式时。
  • 避免客户端代码与具体类耦合,支持产品族的切换(例如从 Windows 风格切换到 Mac 风格)。
2. 关键角色
  • Abstract Factory(抽象工厂) :声明创建产品对象的方法(如 CreateButton(), CreateTextBox())。
  • Concrete Factory(具体工厂) :实现抽象工厂接口,生成具体产品(如 WindowsFactory, MacFactory)。
  • Abstract Product(抽象产品) :定义产品的接口(如 Button, TextBox)。
  • Concrete Product(具体产品) :实现抽象产品接口(如 WindowsButton, MacButton)。
3. 类图

二、模式特点

优点

  1. 产品族一致性:确保创建的对象属于同一家族(例如不会混用 Windows 按钮和 Mac 文本框)。
  2. 解耦客户端与具体类:客户端仅依赖抽象接口,与具体实现无关。
  3. 易于切换产品族 :只需更换具体工厂(如 WindowsFactoryMacFactory)。

缺点

  1. 扩展新产品困难 :若新增产品类型(如 Checkbox),需修改所有工厂接口。
  2. 代码复杂度增加:需要定义大量接口和类。

三、适用场景

1. 需要创建一组相关或依赖的对象

抽象工厂模式的核心是创建一组相互关联或依赖的对象,这些对象通常属于同一个产品族。以下是一些典型场景:

示例 1:跨平台 UI 组件库

  • 场景:开发一个支持多平台(如 Windows、Mac、Linux)的 UI 组件库,每个平台有自己风格的按钮、文本框、下拉框等组件。
  • 问题:如果直接硬编码创建组件,会导致代码与具体平台耦合,难以扩展和维护。
  • 解决方案 :使用抽象工厂模式,为每个平台创建一个工厂(如 WindowsFactoryMacFactory),每个工厂负责创建该平台的所有组件。

示例 2:游戏中的角色装备

  • 场景:游戏中不同种族(如人类、精灵、兽人)的角色需要穿戴不同风格的装备(如武器、盔甲、鞋子)。
  • 问题:如果直接创建装备对象,可能会导致人类角色穿戴精灵风格的装备,破坏游戏一致性。
  • 解决方案 :使用抽象工厂模式,为每个种族创建一个工厂(如 HumanFactoryElfFactory),确保创建的装备风格一致。

2. 系统需要独立于产品的创建、组合和表示

抽象工厂模式将产品的创建过程封装在工厂中,客户端代码只需要依赖抽象接口,而不需要关心具体实现。

示例 3:数据库访问层

  • 场景:系统需要支持多种数据库(如 MySQL、PostgreSQL、Oracle),每种数据库有自己的连接、命令、事务等对象。
  • 问题:如果直接在业务逻辑中创建数据库对象,会导致代码与具体数据库耦合,难以切换数据库。
  • 解决方案 :使用抽象工厂模式,为每种数据库创建一个工厂(如 MySQLFactoryPostgreSQLFactory),客户端通过工厂获取数据库对象,无需关心具体实现。

示例 4:主题切换

  • 场景:应用程序支持多种主题(如白天模式、夜间模式),每种主题有不同的颜色、字体、图标等。
  • 问题:如果直接在代码中硬编码主题样式,会导致代码难以维护和扩展。
  • 解决方案 :使用抽象工厂模式,为每个主题创建一个工厂(如 LightThemeFactoryDarkThemeFactory),客户端通过工厂获取主题相关的对象。

3. 需要确保产品之间的兼容性

抽象工厂模式确保创建的对象属于同一个产品族,从而保证它们之间的兼容性。

示例 5:操作系统与硬件驱动

  • 场景:开发一个操作系统,需要支持不同硬件厂商的驱动程序(如显卡驱动、声卡驱动、网卡驱动)。
  • 问题:如果直接创建驱动对象,可能会导致不兼容的驱动组合(如 Intel 显卡驱动与 AMD 声卡驱动)。
  • 解决方案 :使用抽象工厂模式,为每个硬件厂商创建一个工厂(如 IntelFactoryAMDFactory),确保创建的驱动对象属于同一厂商。

示例 6:电商平台的支付与物流

  • 场景:电商平台需要支持多种支付方式(如支付宝、微信支付)和物流方式(如顺丰、京东物流)。
  • 问题:如果直接创建支付和物流对象,可能会导致不兼容的组合(如支付宝与京东物流)。
  • 解决方案 :使用抽象工厂模式,为每个支付和物流组合创建一个工厂(如 AlipaySFExpressFactoryWeChatJDLogisticsFactory),确保支付和物流对象兼容。

4. 需要动态切换产品族

抽象工厂模式支持在运行时动态切换产品族,而无需修改客户端代码。

示例 7:多语言支持

  • 场景:应用程序需要支持多语言(如中文、英文、日文),每种语言有不同的界面文本、日期格式、货币符号等。
  • 问题:如果直接在代码中硬编码语言相关的对象,会导致代码难以维护和扩展。
  • 解决方案 :使用抽象工厂模式,为每种语言创建一个工厂(如 ChineseFactoryEnglishFactory),客户端通过工厂获取语言相关的对象,支持动态切换语言。

示例 8:游戏中的场景切换

  • 场景:游戏中不同场景(如森林、沙漠、雪地)有不同的背景、音效、角色模型。
  • 问题:如果直接在代码中创建场景对象,会导致代码与具体场景耦合,难以扩展。
  • 解决方案 :使用抽象工厂模式,为每个场景创建一个工厂(如 ForestFactoryDesertFactory),客户端通过工厂获取场景相关的对象,支持动态切换场景。

5. 需要隐藏具体产品的实现细节

抽象工厂模式将具体产品的创建过程封装在工厂中,客户端只需要依赖抽象接口,无需关心具体实现。

示例 9:日志系统

  • 场景:系统需要支持多种日志存储方式(如文件日志、数据库日志、云存储日志)。
  • 问题:如果直接在代码中创建日志对象,会导致代码与具体存储方式耦合。
  • 解决方案 :使用抽象工厂模式,为每种日志存储方式创建一个工厂(如 FileLogFactoryDatabaseLogFactory),客户端通过工厂获取日志对象,无需关心具体实现。

示例 10:缓存系统

  • 场景:系统需要支持多种缓存存储方式(如内存缓存、Redis 缓存、Memcached 缓存)。
  • 问题:如果直接在代码中创建缓存对象,会导致代码与具体存储方式耦合。
  • 解决方案 :使用抽象工厂模式,为每种缓存存储方式创建一个工厂(如 MemoryCacheFactoryRedisCacheFactory),客户端通过工厂获取缓存对象,无需关心具体实现。

四、Go 语言代码示例

场景描述

假设需要开发一个跨平台的 UI 组件库 ,支持 Windows 和 Mac 两种风格,每个风格包含按钮(Button)和文本框(TextBox)。使用抽象工厂模式实现组件创建。

代码实现

go 复制代码
package abstract_factory_demo

type Phone interface {
	Call(number string)
}

type SmartSpeaker interface {
	PlayMusic(song string)
}

type HuaweiPhone struct {
}

func (h *HuaweiPhone) Call(number string) {
	println("华为手机拨打电话:" + number)
}

type HuaweiSmartSpeaker struct {
}

func (h *HuaweiSmartSpeaker) PlayMusic(song string) {
	println("华为智能音箱播放音乐:" + song)
}

type XiaomiPhone struct {
}

func (x *XiaomiPhone) Call(number string) {
	println("小米手机拨打电话:" + number)
}

type XiaomiSmartSpeaker struct {
}

func (x *XiaomiSmartSpeaker) PlayMusic(song string) {
	println("小米智能音箱播放音乐:" + song)
}

// 抽象工厂接口
type DeviceFactory interface {
	CreatePhone() Phone
	CreateSmartSpeaker() SmartSpeaker
}

// 华为工厂
type HuaweiFactory struct {
}

func (hf *HuaweiFactory) CreateSmartSpeaker() SmartSpeaker {
	return &HuaweiSmartSpeaker{}
}

func (hf *HuaweiFactory) CreatePhone() Phone {
	return &HuaweiPhone{}
}

// 小米工厂
type XiaomiFactory struct {
}

func (xf *XiaomiFactory) CreatePhone() Phone {
	return &XiaomiPhone{}
}

func (xf *XiaomiFactory) CreateSmartSpeaker() SmartSpeaker {
	return &XiaomiSmartSpeaker{}

}

func getFactory(brand string) DeviceFactory {
	if brand == "huawei" {
		return &HuaweiFactory{}
	} else if brand == "xiaomi" {
		return &XiaomiFactory{}
	}
	return nil
}

func test() {
	// 华为工厂
	huaweiFactory := getFactory("huawei")
	huaweiPhone := huaweiFactory.CreatePhone()
	huaweiSmartSpeaker := huaweiFactory.CreateSmartSpeaker()
	huaweiPhone.Call("123456")
	huaweiSmartSpeaker.PlayMusic("夜曲")
	// 小米工厂
	xiaomiFactory := getFactory("xiaomi")
	xiaomiPhone := xiaomiFactory.CreatePhone()
	XiaomiSmartSpeaker := xiaomiFactory.CreateSmartSpeaker()
	xiaomiPhone.Call("654321")
	XiaomiSmartSpeaker.PlayMusic("稻香")
}

输出结果

plaintext 复制代码
=== RUN   Test_test
华为手机拨打电话:123456
华为智能音箱播放音乐:夜曲
小米手机拨打电话:654321
小米智能音箱播放音乐:稻香
--- PASS: Test_test (0.00s)
PASS

五、与其他模式对比

  • 工厂方法模式:关注单一产品的创建,而抽象工厂关注产品族的创建。
  • 建造者模式:分步骤构建复杂对象,抽象工厂直接返回完整产品族。
相关推荐
大地之灯2 小时前
深度学习每周学习总结R6(RNN实现阿尔茨海默病诊断)
rnn·深度学习·学习
不会敲代码的狗3 小时前
Acwing-基础算法课笔记之基础算法(差分)
笔记·算法
嗷嗷哦润橘_5 小时前
Deepseek系列从v3到R易背面经版
开发语言·人工智能·笔记·deepseek
霜雪殇璃5 小时前
(定时器,绘制事件,qt简单服务器的搭建)2025.2.11
运维·服务器·qt·学习
漂亮_大男孩6 小时前
深度学习|表示学习|Instance Normalization 全面总结|26
人工智能·深度学习·神经网络·学习·cnn
S19016 小时前
Django学习笔记(第一天:Django基本知识简介与启动)
笔记·学习·django
DXX——8 小时前
嵌入式基础学习|C语言篇——结构体(含进阶)二
c语言·开发语言·学习
feifeikon8 小时前
NLP&深度学习 DAY7:平滑、语境学习、Scaling Law、大模型的发展、LLM的构建流程
深度学习·学习·自然语言处理
安和昂8 小时前
effective—Objective—C 第七章阅读笔记
笔记·objective-c