【创造型模式】抽象工厂方法模式

文章目录

抽象工厂方法模式

工厂方法模式引入了"工厂等级结构",解决了简单工厂方法过分依赖单一工厂的问题。但是工厂方法模式存在的一个问题是,针对每一种产品,都需要设计一种工厂,比如对于"苹果"和"山东苹果",我们就需要分别设计一个"苹果工厂"和"山东苹果工厂"。

工厂方法模式现有的问题在于:

  1. 但添加一个新产品的时候(比如葡萄),虽然遵循开闭原则,不修改现有的代码,但是需要添加大量的类(比如辽宁葡萄、河北葡萄、山东葡萄),而且需要添加相对应的工厂,增加了系统开销和维护成本。
  2. 如果同一个"地域"有多种产品,比如"辽宁葡萄"、"辽宁樱桃"、"辽宁苹果",那么需要分别创建具体的工厂,而不能通过一个工厂来生产所有的产品。虽然该方法满足开闭原则,但是代码将会变得非常复杂,不够好。

抽象工厂方法模式的引入进一步优化了工厂方法模式。具体来说,抽象工厂方法模式引入了"产品等级结构"和"产品族"这两个概念。

产品族与产品等级结构

此处借用《Easy 搞定 Golang 设计模式》当中的原图:

  • 产品族:具有同一个地区、同一个厂商、同一个开发包、同一个组织模块等隶属关系,但是具备不同的特点或功能,这样的产品构成的集合,就是一个产品族。比如产自同一个产地的各种水果,就构成一个产品族。
  • 产品等级结构:具有相同特点或功能,但是隶属的组织模块不同,这样的产品结构,称为一个产品等级。不同产地的同一种水果就是同一个产品等级。

"抽象工厂方法模式"针对"产品族"进行产品生产。

抽象工厂方法模式的角色和职责

  • 抽象工厂角色:声明了一组用于创建一组产品的方法 ,每一个方法对应一种产品。
  • 具体工厂角色:实现了在抽象工厂中声明的创建产品的方法,生成一组具体的产品,这些产品构成一个产品族,每一个产品都位于某个产品结构当中。
  • 抽象产品角色:为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
  • 具体产品角色:定义具体工厂生产的具体产品对象,实现抽象产品接口声明的业务方法。

抽象工厂方法模式的实现

go 复制代码
package main

import "fmt"

// ---------- 抽象层 ----------
type AbstractApple interface {
	ShowApple()
}

type AbstractBanana interface {
	ShowBanana()
}

type AbstractPear interface {
	ShowPear()
}

// 抽象工厂: 定义了工厂可以生产哪些抽象产品
type AbstractFactory interface {
	CreateApple() AbstractApple
	CreateBanana() AbstractBanana
	CreatePear() AbstractPear
}

// ---------- 实现层 ----------
type LiaoningApple struct{}

func (la *LiaoningApple) ShowApple() {
	fmt.Println("Liaoning Apple")
}

type LiaoningBanana struct{}

func (lb *LiaoningBanana) ShowBanana() {
	fmt.Println("Liaoning Banana")
}

type LiaoningPear struct{}

func (lp *LiaoningPear) ShowPear() {
	fmt.Println("Liaoning Pear")
}

type LiaoningFactory struct{}

func (fa *LiaoningFactory) CreateApple() AbstractApple {
	return &LiaoningApple{}
}

func (fa *LiaoningFactory) CreateBanana() AbstractBanana {
	return &LiaoningBanana{}
}

func (fa *LiaoningFactory) CreatePear() AbstractPear {
	return &LiaoningPear{}
}

type JiangsuApple struct{}

func (ja *JiangsuApple) ShowApple() {
	fmt.Println("Jiangsu Apple")
}

type JiangsuBanana struct{}

func (jb *JiangsuBanana) ShowBanana() {
	fmt.Println("Jiangsu Banana")
}

type JiangsuPear struct{}

func (jp *JiangsuPear) ShowPear() {
	fmt.Println("Jiangsu Pear")
}

type JiangsuFactory struct{}

func (fa *JiangsuFactory) CreateApple() AbstractApple {
	return &JiangsuApple{}
}

func (fa *JiangsuFactory) CreateBanana() AbstractBanana {
	return &JiangsuBanana{}
}

func (fa *JiangsuFactory) CreatePear() AbstractPear {
	return &JiangsuPear{}
}

type BeijingApple struct{}

func (ba *BeijingApple) ShowApple() {
	fmt.Println("Beijing Apple")
}

type BeijingBanana struct{}

func (bb *BeijingBanana) ShowBanana() {
	fmt.Println("Beijing Banana")
}

type BeijingPear struct{}

func (pbp *BeijingPear) ShowPear() {
	fmt.Println("Beijing Pear")
}

type BeijingFactory struct{}

func (fa *BeijingFactory) CreateApple() AbstractApple {
	return &BeijingApple{}
}

func (fa *BeijingFactory) CreateBanana() AbstractBanana {
	return &BeijingBanana{}
}

func (fa *BeijingFactory) CreatePear() AbstractPear {
	return &BeijingPear{}
}

func main() {
	// 创建辽宁的苹果, 香蕉, 梨等对象
	var liaoningFac AbstractFactory
	liaoningFac = &LiaoningFactory{}

	var liaoningApple AbstractApple
	liaoningApple = liaoningFac.CreateApple()
	liaoningApple.ShowApple()

	var liaoningBanana AbstractBanana
	liaoningBanana = liaoningFac.CreateBanana()
	liaoningBanana.ShowBanana()

	var liaoningPear AbstractPear
	liaoningPear = liaoningFac.CreatePear()
	liaoningPear.ShowPear()

	// 创建其他产区的水果
	jiangsuFac := &JiangsuFactory{}

	jiangsuApple := jiangsuFac.CreateApple()
	jiangsuApple.ShowApple()

	jiangsuBanana := jiangsuFac.CreateBanana()
	jiangsuBanana.ShowBanana()

	jiangsuPear := jiangsuFac.CreatePear()
	jiangsuPear.ShowPear()

	beijingFac := &BeijingFactory{}

	beijingApple := beijingFac.CreateApple()
	beijingApple.ShowApple()

	beijingBanana := beijingFac.CreateBanana()
	beijingBanana.ShowBanana()

	beijingPear := beijingFac.CreatePear()
	beijingPear.ShowPear()
}

抽象工厂方法模式的优缺点

优点:

  • 继承了工厂方法模式的优点;
  • 确保客户端始终只使用一个同产品族中的对象;
  • 增加新的产品族很方便,对于上例而言,可以直接设计一个新的工厂并实现抽象工厂的接口。

缺点:

  • 新增产品的等级结构复杂,需要对原有系统进行较大的修改,甚至可能修改抽象层的代码。

适用场景

  • 系统中有多于一个产品族,每次只使用某个产品族。
  • 产品等级结构问题,设计系统完成后,不会向系统中新增产品等级结构或删除已有的产品等级结构。
相关推荐
星心源七境1 小时前
七境体系全解析:从六韬兵法到AI锁颜,一套贯穿古典智慧与现代应用的成长操作系统
人工智能·设计模式·设计
qq_297574672 小时前
设计模式系列文章(基础篇第21篇):迭代器模式——遍历聚合解耦,实现统一迭代访问
设计模式·迭代器模式
禅思院4 小时前
前端请求取消与调度完全指南:从 AbortController 到企业级优先级架构
前端·设计模式·前端框架
小bo波5 小时前
用匿名内部类优雅地计算方法执行时间
java·设计模式·性能测试·模板方法模式·lambda·代码优化·匿名内部类
写代码的小阿帆6 小时前
行为型设计模式之观察者(发布-订阅)模式
设计模式
王_teacher6 小时前
23种设计模式全解析(GoF 设计模式)
设计模式·软考·软件设计师·软考中级
阿坤带你走近大数据7 小时前
分别介绍下java主流的开发框架、设计模式与对应编程语言的高级特性
java·开发语言·设计模式
geovindu7 小时前
go: Coroutines Pattern
开发语言·后端·设计模式·golang·协程模式
Anastasiozzzz8 小时前
构建健壮软件系统的基石:深入解析面向对象设计七大原则
开发语言·javascript·设计模式·ecmascript
qq_297574671 天前
设计模式系列文章(基础篇第19篇):中介者模式——封装交互关系,解耦网状依赖
设计模式·交互·中介者模式