[go] 抽象工厂模式

简介: [go] 抽象工厂模式

抽象工厂模式


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


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


模型说明


  • 抽象产品(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 
---------------------------
相关文章
|
3月前
|
安全 测试技术 Go
|
3月前
|
Go 容器
|
3月前
|
设计模式 Java Go
什么是Go 中的单例模式?
本文介绍了Go语言中的单例设计模式,包括饿汉式与懒汉式两种实现方式。饿汉式单例在程序启动时即完成实例化,适用于不需延迟加载的情况;通过全局变量初始化确保实例唯一性。懒汉式单例采用延迟初始化策略,在首次请求时创建实例,适合资源消耗较大的场景;利用双重检查锁定机制保证多线程环境下的安全性。两种模式各有优劣,开发者应根据实际需求选择合适的实现方案。
|
3月前
|
设计模式 Go
|
3月前
|
设计模式 Go
|
3月前
|
设计模式 监控 Go
|
3月前
|
缓存 算法 Go
|
3月前
|
存储 设计模式 缓存