抽象工厂——工厂的工厂
工厂方法将一族相关对象分组在一起,如果我们将对象族按更结构化的层次分组会怎样?
描述
抽象工厂设计模式是一个新的分组层,用于实现更大更复杂的组合对象,该对象通过接口使用。对族中的对象分组和对族进行分组的想法是要拥有可以互换且更容易成长的大型工厂。开发的早期阶段,与工厂和抽象工厂合作要比等到所有具体实现都完成再启动代码要容易的多。另外,除非我们知道在特定领域的库存将非常大并且很容易的分为几类,否则不会编写抽象工厂。
目标
当对象数量增长到足以创建一个唯一的点来获取所有对象时,对相关产品族对象进行分组是非常方便的,这是获得运行时对象创建灵活性的唯一方法。
- 为工厂方法提供新的封装层,以返回所有工厂的公共接口
- 将普通工厂分组为超级工厂(工厂的工厂)
例子
再以整车制造为例,我们需要重用在建造者模式中实现的工厂。我们希望展示使用不同方法来解决同一问题的相似性,以便看到每一种方法的优缺点。中间会展示Go的隐式接口功能,因为我们不需要接触任何东西,最后将创建一个新的工厂来创建装运订单。
首先是整车工厂(抽象工厂),该接口定义了一个具有Build方法(输入值为工厂类型,返回值为Vehicle,也是一个接口,所有车辆都应实现该接口,和一个错误信息)的工厂,所有具体工厂应实现该接口。
type VehicleFactory interface {
Build(v int) (Vehicle, error)
}
其次是BuildFactory方法,输入一个工厂类型,输出值为具体工厂和错误信息。该方法根据输入的类型信息,产生对应的工厂。
const (
CarFactoryType = 1
MotorbikeFactoryType = 2
)
func BuildFactory(f int) (VehicleFactory, error) {
switch f {
case CarFactoryType:
return new(CarFactory), nil
case MotorbikeFactoryType:
return new(MotorbikeFactory), nil
default:
return nil, errors.New(fmt.Sprintf("Factory with id %d not recognized\n", f))
}
}
具体工厂的定义如下:
const (
LuxuryCarType = 1
FamilyCarType = 2
)
type CarFactory struct{}
func (c *CarFactory) Build(v int) (Vehicle, error) {
switch v {
case LuxuryCarType:
return new(LuxuryCar), nil
case FamilyCarType:
return new(FamilyCar), nil
default:
return nil, errors.New(fmt.Sprintf("Vehicle of type %d not recognized\n", v))
}
}
具体工厂中接受一个具体车辆的类型,返回对应的车辆实例。
测试
func TestCarFactory(t *testing.T) {
carF, err := BuildFactory(CarFactoryType)
if err != nil {
t.Fatal(err)
}
carVehicle, err := carF.Build(LuxuryCarType)
if err != nil {
t.Fatal(err)
}
t.Logf("Car vehicle has %d seats\n", carVehicle.NumWheels())
luxuryCar, ok := carVehicle.(Car)
if !ok {
t.Fatal("Struct assertion has failed")
}
t.Logf("Luxury var has %d doors.\n", luxuryCar.NumDoors())
}
测试代码中首先根据BuildFactory方法获取对应的工厂方法,检查是否出错,再根据对应的工厂方法产出对应的car,再访问Vehicle接口的NumWheels方法获取具体信息,根据类型断言luxuryCar, ok := carVehicle.(Car)确定该类型是不是所期待的具体类型,最后访问具体类型的与接口不同的方法,确定luxuryCar的门有4个。
完整代码见 https://github.com/ricardoliu404/go-design-patterns/tree/master/creational/abstract_factory
1万+

被折叠的 条评论
为什么被折叠?



