golang实现设计模式之抽象工厂模式总结-代码、优缺点、适用场景

发布时间 2023-05-31 15:56:39作者: 进击的davis

抽象工厂模式也是一种创建型的设计模式,其是在工厂模式的基础上实现更高程度的内聚。我们知道在工厂模式中,一种产品类就需要新建个对应的工厂类生成产品的实例,这会有什么问题呢?

虽然工厂模式解决了简单工厂模式不好扩展的问题,实现了OCP,但一种产品就需要新建一个工厂类,比如有10000种产品,是不是也是新建10000个工厂类呢?看到没,这就是问题所在,即使利于扩展,无奈代码臃肿,而且有些产品可以提出共性,尽量复用就成为了改进的目标。

抽象工厂模式就是实现了比较好的内聚,将原来工厂模式下的一种产品类等级,优化为多个有一定关联的产品类聚合在一起。

下面老规矩,看看抽象模式的优缺点、适用场景、代码实现。

优缺点

  • 优点

1.具备工厂方法的优点。

2.同时由于可以聚合多个产品族的共性,不用创建新类来管理。

  • 缺点

1.产品族的扩展将是一件十分费力的事情。新增产品时,所有工厂类需要联动修改,所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

适用场景

  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

代码实现

package main

import "fmt"

func main()  {
   var f factory
   f = new(concreteFactoryA)
   p := f.createPhoneFactory()
   p.use()
   w := f.createSmartWatchFactory()
   w.healthWatcher()
}

// 1.cellphone interface
type iCellphone interface {
   use()
}

// 1.smart watch interface
type iSmartWatch interface {
   healthWatcher()
}

// 2.concrete cellphone product
type iphoneProduct struct {

}

func (r *iphoneProduct) use()  {
   fmt.Println("Iphone can be dialing.")
}

type miPhoneProduct struct {

}

func (r *miPhoneProduct) use()  {
   fmt.Println("miPhone can be dialing.")
}

type iWatchProduct struct {

}

func (r *iWatchProduct) healthWatcher()  {
   fmt.Println("iWatch can monitor your health.")
}

type oppoWatchProduct struct {

}

func (r *oppoWatchProduct) healthWatcher()  {
   fmt.Println("oppoWatch can monitor your health.")
}

type phoneTyp int

type watchType int

const (
   iphoneType = 0 + iota
   miPhoneTyp
)

const (
   iWatchType = 10000 + iota
   oppoWatchTyp
)

// 3.factory interface
type factory interface {
   createPhoneFactory() iCellphone
   createSmartWatchFactory() iSmartWatch
}

// 4.concrete product factory
// apple product
type concreteFactoryA struct {

}

func (r *concreteFactoryA) createPhoneFactory() iCellphone {
   return &iphoneProduct{}
}

func (r *concreteFactoryA) createSmartWatchFactory() iSmartWatch {
   return &iWatchProduct{}
}

// other brands product
type concreteFactoryB struct {

}

func (r *concreteFactoryB) createPhoneFactory() iCellphone {
   return &miPhoneProduct{}
}

func (r *concreteFactoryB) createSmartWatchFactory() iSmartWatch {
   return &oppoWatchProduct{}
}

工厂模式系列目前就结束了,这里做个简单总结:

  • 1.简单工厂模式,客户端只要请求工厂类,传入不同的参数,进而获取到对应的产品实例,客户端不用关心其实现细节,只管获取实例使用即可,实现了创建实例与使用实例的隔离。这种设计模式适合于创建产品种类比较少的情景,如果产品种类很多,可想而知,我们都通过一个工厂类的生成方法来获取,必然涉及到修改新建实例代码,不就违背了 OCP 原则吗。所以对于新建和删除工厂方法中的相关涉及的产品,这也是问题。而且就这一个工厂方法来生成所有的产品的实例,产品多了,代码就臃肿了,使得该方法职责过重。

  • 2.工厂模式,为了解决工厂方法只有一个,职责过重,工厂模式中通过一种产品对应一个具体的工厂类去实现实例的生成,一定程度上解耦了功能,另外如果新增产品,我们只需要多写个产品类和对象的工厂类及方法,这也很好的实现了 OCP原则,对扩展开放,对修改关闭。当然这也有问题,就是产品多了,每个产品都需要新建个对应的工厂类,况且有些产品也并不是完全不相关,内聚性就变差了。工厂模式适用于客户端不关心实例产生细节,另外实例的实际创建会推迟到子类工厂中实现。

  • 3.抽象工厂模式,既然工厂模式每个产品都需要实现对应的工厂类去生成相关实例,提取产品的共性,提高代码的内聚性,就是抽象工厂模式要干的。在抽象工厂中,依然是不同产品对应不同的工厂类,但可以尽可能将具有相同共性的产品类别合在一起,从而提高了内聚性。但同时也带来一些问题,比如修改产品类,可能涉及到对应的工厂类都需要改动,OCP原则有没有很好的遵守,而且通过更加地抽象化,也增加了代码的理解难度。

没有万能的设计模式,只有合适的,有的时候也不必过于拘泥于规则,实际编码中,尽量遵守,寻找到合适的模式,让代码实现高内聚、低耦合、可扩展。

参考: