创建型设计模式——抽象工厂模式

文章目录

抽象工厂模式(Abstract Factory)基于工厂方法模式。两者的区别在于:工厂方法模式是创建出一种产品,而抽象工厂模式是创建出一类产品。这二种都属于工厂模式,在设计上是相似的。

抽象工厂模式和工厂方法不太一样,它要解决的问题比较复杂,不但工厂是抽象的,产品是抽象的,而且有多个产品需要创建,因此,这个抽象工厂会对应到多个实际工厂,每个实际工厂负责创建多个实际产品。

抽象工厂模式适合应用场景:

  • 如果代码需要与多个不同系列的相关实体交互,但是由于无法提前获取相关信息,或者出于对未来扩展性的考虑,你不希望代码基于实体的具体类进行构建,在这种情况下,你可以使用抽象工厂。
  • 如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式。

问题

假设,有一个文章存储工厂,提供 Redis 和 MySQL 两种存储数据的方式。使用工厂方法模式,我们就需要一个文章存储工厂,并提供 Redis 和 MySQL 的存储方法。

如果此时业务还需要分成存储散文和古诗两种载体,这两种载体都可以进行 Redis 和 MySQL 存储。就可以使用抽象工厂模式,我们需要一个存储工厂作为父工厂,散文工厂和古诗工厂作为子工厂,并提供对应的保存方法。

解决

以上文的存储工厂业务为例,用抽象工厂模式的思路来设计代码,就像下面这样:

package main

import "fmt"

// StorageFactory 抽象存储工厂
type StorageFactory interface {
	CreateProse() Prose   // 生产抽象散文产品
	CreatePoetry() Poetry // 生产抽象古诗产品
}

// 抽象散文产品
type Prose interface {
	Save()
}

// 抽象古诗产品
type Poetry interface {
	Save()
}

// 具体 redis 散文产品
type RedisProse struct{}

func (*RedisProse) Save() {
	fmt.Println("Redis Save Prose")
}

// 具体 redis 古诗产品
type RedisPoetry struct{}

func (*RedisPoetry) Save() {
	fmt.Println("Redis Save Poetry")
}

// 具体 mysql 散文产品
type MySQLProse struct{}

func (*MySQLProse) Save() {
	fmt.Println("MySQL Save Prose")
}

// 具体 mysql 古诗产品
type MySQLPoetry struct{}

func (*MySQLPoetry) Save() {
	fmt.Println("MySQL Save Poetry")
}

// 具体 redis 存储工厂
type RedisFactory struct{}

func (*RedisFactory) CreateProse() Prose {
	return &RedisProse{}
}

func (*RedisFactory) CreatePoetry() Poetry {
	return &RedisPoetry{}
}

// 实现 mysql 存储工厂
type MySQLFactory struct{}

func (*MySQLFactory) CreateProse() Prose {
	return &MySQLProse{}
}

func (*MySQLFactory) CreatePoetry() Poetry {
	return &MySQLPoetry{}
}

func Save(storageFactory StorageFactory) {
	storageFactory.CreateProse().Save()
	storageFactory.CreatePoetry().Save()
}

func main() {
	var factory StorageFactory
	factory = &RedisFactory{}
	Save(factory)

	factory = &MySQLFactory{}
	Save(factory)
}

运行示例

参考文章:


也可以看看


全国大流量卡免费领

19元月租ㆍ超值优惠ㆍ长期套餐ㆍ免费包邮ㆍ官方正品