设计模式-05-抽象工厂模式

工厂模式分为三种更加细分的类型

  1. 简单工厂(Simple Factory)
  2. 工厂方法(Factory Method)
  3. 抽象工厂(Abstract Factory)

逻辑结构

AbstactFactory

代码实现

代码路径:https://github.com/XBoom/DesignPatterns/tree/main/04_AbstractFactory

  1. 有一个简单的产品接口(这里指汽车)

    1
    2
    3
    type Car interface {
    Name() string
    }
  2. 有两个具体的实现类

    1
    2
    3
    4
    5
    6
    7
    8
    type BYD struct {
    }

    func (B BYD) Name() string {
    return "BYD"
    }

    var _ Car = (*BYD)(nil)

    另外一个具体类

    1
    2
    3
    4
    5
    6
    7
    8
    type Tesla struct {
    }

    func (t Tesla) Name() string {
    return "Tesla"
    }

    var _ Car = (*Tesla)(nil)
  3. 工厂方法有一个抽象接口,对应具体的产品

    1
    2
    3
    4
    type Factory interface {
    CreateBYD() Car
    CreateTesla() Car
    }
  4. 实现工厂的具体对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    type WuhanFactory struct {
    }

    func (w WuhanFactory) CreateBYD() Car {
    return &BYD{}
    }

    func (w WuhanFactory) CreateTesla() Car {
    return &Tesla{}
    }

    var _ Factory = (*WuhanFactory)(nil)

    另外一个实现对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    type ShangHaiFactory struct {
    }

    func (s ShangHaiFactory) CreateBYD() Car {
    return &BYD{}
    }

    func (s ShangHaiFactory) CreateTesla() Car {
    return &Tesla{}
    }

    var _ Factory = (*ShangHaiFactory)(nil)

提供一个创建一系列相关或相互依赖对象的接口 Factory,而无需指定它们具体的类。即通过一个工厂接口来创建一组相关联的对象,由具体的工厂 WuhanFactoryShangHaiFactory 实现这个接口并创建一系列相关的对象。这样做的好处是能够保证一系列对象被一起创建,并且这些对象之间相互协调

抽象工厂:每个工厂都能产生全系列产品,这个全系列在抽象工厂接口中定义

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var expectBYD = "BYD"
var expectTesla = "Tesla"

func TestShangHaiFactory(t *testing.T) {
factory := new(ShangHaiFactory)
byd := factory.CreateBYD()
if !reflect.DeepEqual(byd.Name(), expectBYD) {
t.Fatalf("expect %s acture %s", expectBYD, byd.Name())
}
tesla := factory.CreateTesla()
if !reflect.DeepEqual(tesla.Name(), expectTesla) {
t.Fatalf("expect %s acture %s", expectTesla, tesla.Name())
}

}

func TestWuhanFactory(t *testing.T) {
factory := new(WuhanFactory)
byd := factory.CreateBYD()
if !reflect.DeepEqual(byd.Name(), expectBYD) {
t.Fatalf("expect %s acture %s", expectBYD, byd.Name())
}
tesla := factory.CreateTesla()
if !reflect.DeepEqual(tesla.Name(), expectTesla) {
t.Fatalf("expect %s acture %s", expectTesla, tesla.Name())
}
}

总结

工厂方法与抽象工厂的区别:

  • 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。即通过一个公共的接口来创建具体的对象,由子类来实现这个接口并创建具体的对象。这样做的好处是将具体类的实例化过程封装到子类中,符合开闭原则,有利于系统的扩展。

  • 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。即通过一个工厂接口来创建一组相关联的对象,由具体的工厂实现这个接口并创建一系列相关的对象。这样做的好处是能够保证一系列对象被一起创建,并且这些对象之间相互协调

抽象工厂模式并没有违背开闭原则,当需要新增一族产品时,只需要扩展抽象工厂接口,并创建对应的具体工厂类来实现该接口。保证在不影响现有功能的情况下,增加新的功能(在抽象接口中新增类型不算修改…)

在实际应用中,如果需要创建一系列相关或依赖的对象,可以选择抽象工厂模式;如果需要创建单个对象,并且需要扩展性和灵活性,可以选择工厂方法模式。所以抽象工厂并不是工厂方式的优化,两者应用场景不一样

参考文档

  1. https://lailin.xyz/post/factory.html
  2. https://github.com/senghoo/golang-design-pattern