[go] 抽象工厂模式

发布时间:2024年01月18日

抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂模式经常以工厂方法的方式实现。

模型说明

  • 抽象产品(Abstract Product)为构成系列产品的一组不同但相关的产品声明接口。
  • 具体产品(Concrete Product)是抽象产品的多种不同类型实现。 所有变体(维多利亚/现代)都必须实现相应的抽象产品(椅子/沙发)。
  • 抽象工厂(Abstract Factory)接口声明了一组创建各种抽象产品的方法。
  • 具体工厂(Concrete Factory)实现抽象工厂的构建方法。 每个具体工厂都对应特定产品变体, 且仅创建此种产品变体。
  • 尽管具体工厂会对具体产品进行初始化,其构建方法签名必须返回相应的抽象产品。这样,使用工厂类的客户端代码就不会与工厂创建的特定产品变体耦合。客户端(Client)只需通过抽象接口调用工厂和产品对象,就能与任何具体工厂/产品变体交互。

优缺点

1.优点

  • 你可以确保同一工厂生成的产品相互匹配。
  • 你可以避免客户端和具体产品代码的耦合。
  • *单一职责原则:*你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
  • *开闭原则:*向应用程序中引入新产品变体时, 你无需修改客户端代码。

2.缺点

  • 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。

使用场景

如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。

参考代码

在上篇文章的基础上,小米和华为都要生产手表的时候,我们应该怎么编码?

// factory.go
// 抽象工厂,包含一系列创建产品的抽象
type IFactory interface {
	makePhone() IPhone
	makeWatch() IWatch
}

func GetFactory(tp string) IFactory {
	if tp == "xiaomi" {
		return &Xiaomi{}
	} else if tp == "huawei" {
		return &Huawei{}
	} else {
		panic("not found type")
	}
	return nil
}

// 具体工厂类
type Xiaomi struct{}

func (x *Xiaomi) makePhone() IPhone {
	return &Phone{
		name:  "xiaomi 12",
		price: 3999,
	}
}

func (x *Xiaomi) makeWatch() IWatch {
	return &Watch{
		name:  "miWatch",
		price: 299,
	}
}

type Huawei struct{}

func (h *Huawei) makePhone() IPhone {
	return &Phone{
		name:  "iPhone 14",
		price: 6999,
	}
}

func (h *Huawei) makeWatch() IWatch {
	return &Watch{
		name:  "apple watch",
		price: 2999,
	}
}
// product.go
// 抽象产品
type IPhone interface {
	setPhoneName(name string)
	setPhonePrice(price float64)
	getPhoneName() string
	getPhonePrice() float64
}

type IWatch interface {
	setWatchName(name string)
	setWatchPrice(price float64)
	getWatchName() string
	getWatchPrice() float64
}

// 具体产品类
type Phone struct {
	name  string
	price float64
}

func (g *Phone) setPhoneName(name string) {
	g.name = name
}

func (g *Phone) getPhoneName() string {
	return g.name
}

func (g *Phone) setPhonePrice(price float64) {
	g.price = price
}

func (g *Phone) getPhonePrice() float64 {
	return g.price
}

type Watch struct {
	name  string
	price float64
}

func (w *Watch) setWatchName(name string) {
	w.name = name
}

func (w *Watch) getWatchName() string {
	return w.name
}

func (w *Watch) setWatchPrice(price float64) {
	w.price = price
}

func (w *Watch) getWatchPrice() float64 {
	return w.price
}

// main.go
// 客户端调用
func main() {
	xiaomiFactory := GetFactory("xiaomi")
	xiaomiPhone := xiaomiFactory.makePhone()
	xiaomiWatch := xiaomiFactory.makeWatch()

	huaweiFactory := GetFactory("huawei")
	huaweiPhone := huaweiFactory.makePhone()
	huaweiWatch := huaweiFactory.makeWatch()

	printPhoneDetails(xiaomiPhone)
	printWatchDetails(xiaomiWatch)
	printPhoneDetails(huaweiPhone)
	printWatchDetails(huaweiWatch)
}

func printPhoneDetails(p IPhone) {
	fmt.Printf("Phone: %s", p.getPhoneName())
	fmt.Println()
	fmt.Printf("Price: %.2f", p.getPhonePrice())
	fmt.Println()
	fmt.Println("---------------------------")
}

func printWatchDetails(w IWatch) {
	fmt.Printf("watch: %s", w.getWatchName())
	fmt.Println()
	fmt.Printf("Price: %.2f", w.getWatchPrice())
	fmt.Println()
	fmt.Println("---------------------------")
}

output:

Phone: xiaomi 12 
Price: 3999.00 
--------------------------- 
watch: miWatch 
Price: 299.00 
--------------------------- 
Phone: iPhone 14 
Price: 6999.00 
--------------------------- 
watch: apple watch 
Price: 2999.00 
---------------------------
文章来源:https://blog.csdn.net/ldxxxxll/article/details/135647355
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。