概述
简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同的实例,被创建的实例通常都具有共同的父类。
简单工厂模式属于创建型模式,但不属于 GOF 23 种设计模式。
优缺点及适用环境
优点:
- 实现了创建对象和使用对象的分离;
- 无需知道具体产品的类名;
- 通过引入配置文件,无需修改代码即可更换和增加新的具体产品类,提高系统的灵活性。
缺点:
- 职责过重,一旦程序出错,整个系统都不能运行;
- 引入新的工厂,会导致增加了系统的复杂性和理解难度;
- 违反了开闭原则,一旦新增产品必须修改原有代码;
- 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
适用环境
- 创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂;
- 客户端只需要传入工厂方法参数,无需知道对象如何创建;
实现
角色
工厂方法模式由具体工厂、抽象产品和具体产品等 3 个要素构成。
- 具体工厂(Concrete Factory):它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法 factoryMethod,它的返回类型为抽象产品类型 AbstractProduct。
- 抽象产品(Abstract Product):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。
- 具体产品(Concrete Product):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。
UML 类图如下:
也就是定义一个抽象工厂,其定义了产品的上层接口,但不负责具体的产品,将生成任务交给不同的派生类工厂。这样就不用通过指定类型来创建对象了。
下面我们来讲解该模式:
抽象产品
package simple_factory
// 实现一个抽象的产品
// 声明 AbstractProduct 接口
// 包含 setName 和 getName 方法
type AbstractProduct interface {
SetName(name string)
GetName() string
}
具体产品 1
package simple_factory
// 实现一个具体的产品:ConcreteProduct1 的产品
type ConcreteProduct1 struct {
name string
}
// ConcreteProduct1 的方法 setName
func (b *ConcreteProduct1) SetName(name string) {
b.name = name
}
// ConcreteProduct1 的方法 getName
func (b *ConcreteProduct1) GetName() string {
return "产品 1 的名称是:" + b.name
}
具体产品 2
package simple_factory
// 实现一个具体的产品:ConcreteProduct2 的产品
type ConcreteProduct2 struct {
name string
}
// ConcreteProduct2 的方法 setName
func (b *ConcreteProduct2) SetName(name string) {
b.name = name
}
// ConcreteProduct2 的方法 getName
func (b *ConcreteProduct2) GetName() string {
return "产品 2 的名称是:" + b.name
}
工厂
package simple_factory
type productType string
const (
product1 productType = "product1"
product2 productType = "product2"
)
type Factory struct {
}
// 产品生产工厂
// 具体产品类 ConcreteProduct1 和 ConcreteProduct2 都实现了抽象产品类 AbstractProduct 的接口
// 工厂类实现的两种方法:使用 switch 判断来创建对象
func (c Factory) Create(productType string) AbstractProduct {
switch productType {
case "product1":
// 生产产品 1
return &ConcreteProduct1{}
case "product2":
// 生产产品 2
return &ConcreteProduct2{}
default:
return nil
}
}
测试
package simple_factory
import (
"fmt"
"testing"
)
func TestCar_Create(t *testing.T) {
// 实例化
byd := &ConcreteProduct1{}
byd.SetName("产品1")
fmt.Println(byd.GetName())
// 实例化
bmw := &ConcreteProduct2{}
bmw.SetName("产品2")
fmt.Println(bmw.GetName())
}
func TestCarFactory_Create(t *testing.T) {
// 实例化
carFactory := Factory{}
byd := carFactory.Create(string(product1))
byd.SetName("产品1")
fmt.Println(byd.GetName())
bmw := carFactory.Create(string(product2))
bmw.SetName("产品2")
fmt.Println(bmw.GetName())
}
测试结果
=== RUN TestCar_Create
产品 1 的名称是:产品1
产品 2 的名称是:产品2
--- PASS: TestCar_Create (0.00s)
=== RUN TestCarFactory_Create
产品 1 的名称是:产品1
产品 2 的名称是:产品2
--- PASS: TestCarFactory_Create (0.00s)
PASS
Process finished with exit code 0