工厂模式(Factory Pattern)是一种创建型设计模式,旨在通过定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂模式将对象的创建过程抽象化,客户端不需要了解具体的创建细节,而只需依赖于工厂接口进行对象的创建。
工厂模式的类型
- 简单工厂模式(Simple Factory Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
这里我将详细介绍 简单工厂模式 和 工厂方法模式 的实现,并举例说明它们在 Go 中的应用。
1. 简单工厂模式
简单工厂模式是最基础的一种工厂模式,它通过一个工厂类来实例化不同的产品对象。这个工厂类根据输入的参数返回不同类型的对象。
示例:简单工厂模式
假设我们要构建一个简单的图形绘制程序,需要支持不同类型的图形(例如:圆形、矩形、三角形)。我们将通过一个工厂来创建这些图形对象。
go
package main
import "fmt"
// 图形接口
type Shape interface {
Draw()
}
// 圆形
type Circle struct{}
func (c *Circle) Draw() {
fmt.Println("Drawing a Circle")
}
// 矩形
type Rectangle struct{}
func (r *Rectangle) Draw() {
fmt.Println("Drawing a Rectangle")
}
// 三角形
type Triangle struct{}
func (t *Triangle) Draw() {
fmt.Println("Drawing a Triangle")
}
// 简单工厂
type ShapeFactory struct{}
func (f *ShapeFactory) CreateShape(shapeType string) Shape {
switch shapeType {
case "circle":
return &Circle{}
case "rectangle":
return &Rectangle{}
case "triangle":
return &Triangle{}
default:
return nil
}
}
func main() {
factory := &ShapeFactory{}
// 创建一个圆形
shape := factory.CreateShape("circle")
shape.Draw()
// 创建一个矩形
shape = factory.CreateShape("rectangle")
shape.Draw()
// 创建一个三角形
shape = factory.CreateShape("triangle")
shape.Draw()
}核心概念
- Shape 接口定义了
Draw方法,表示所有形状的绘制功能。 - Circle、Rectangle、Triangle 这些具体类型实现了
Shape接口。 - ShapeFactory 是一个工厂类,根据传入的
shapeType参数来实例化不同的形状。
2. 工厂方法模式
工厂方法模式相较于简单工厂模式,它将对象的创建委托给子类,允许子类决定实例化的具体对象。工厂方法模式不直接在工厂类中实现创建对象的逻辑,而是通过抽象工厂方法来让具体的工厂类决定如何创建产品。
示例:工厂方法模式
继续以上的图形绘制程序,我们将通过工厂方法模式来实现:
go
package main
import "fmt"
// 图形接口
type Shape interface {
Draw()
}
// 圆形
type Circle struct{}
func (c *Circle) Draw() {
fmt.Println("Drawing a Circle")
}
// 矩形
type Rectangle struct{}
func (r *Rectangle) Draw() {
fmt.Println("Drawing a Rectangle")
}
// 工厂接口
type ShapeFactory interface {
CreateShape() Shape
}
// 具体工厂:创建圆形
type CircleFactory struct{}
func (f *CircleFactory) CreateShape() Shape {
return &Circle{}
}
// 具体工厂:创建矩形
type RectangleFactory struct{}
func (f *RectangleFactory) CreateShape() Shape {
return &Rectangle{}
}
func main() {
// 使用圆形工厂
var factory ShapeFactory = &CircleFactory{}
shape := factory.CreateShape()
shape.Draw()
// 使用矩形工厂
factory = &RectangleFactory{}
shape = factory.CreateShape()
shape.Draw()
}核心概念
- Shape 接口定义了
Draw方法。 - Circle 和 Rectangle 是具体的图形对象。
- ShapeFactory 是抽象工厂接口,定义了
CreateShape方法。 - CircleFactory 和 RectangleFactory 是具体的工厂类,负责实例化具体的图形对象。
3. 抽象工厂模式
抽象工厂模式是工厂模式的扩展,它提供了一组相关的工厂方法用于创建一系列产品对象。抽象工厂模式不仅能够创建单一产品,还能创建一组相关的产品。通常情况下,抽象工厂用于当你需要创建一组产品,但每个产品都可以是多个不同类型之一时。
示例:抽象工厂模式
我们继续使用图形绘制的例子,扩展成支持不同风格的图形(例如:现代风格和经典风格)。
go
package main
import "fmt"
// 图形接口
type Shape interface {
Draw()
}
// 现代风格的圆形
type ModernCircle struct{}
func (m *ModernCircle) Draw() {
fmt.Println("Drawing a Modern Circle")
}
// 经典风格的圆形
type ClassicCircle struct{}
func (c *ClassicCircle) Draw() {
fmt.Println("Drawing a Classic Circle")
}
// 现代风格的矩形
type ModernRectangle struct{}
func (m *ModernRectangle) Draw() {
fmt.Println("Drawing a Modern Rectangle")
}
// 经典风格的矩形
type ClassicRectangle struct{}
func (c *ClassicRectangle) Draw() {
fmt.Println("Drawing a Classic Rectangle")
}
// 抽象工厂接口
type ShapeFactory interface {
CreateCircle() Shape
CreateRectangle() Shape
}
// 现代风格的工厂
type ModernFactory struct{}
func (m *ModernFactory) CreateCircle() Shape {
return &ModernCircle{}
}
func (m *ModernFactory) CreateRectangle() Shape {
return &ModernRectangle{}
}
// 经典风格的工厂
type ClassicFactory struct{}
func (c *ClassicFactory) CreateCircle() Shape {
return &ClassicCircle{}
}
func (c *ClassicFactory) CreateRectangle() Shape {
return &ClassicRectangle{}
}
func main() {
// 创建现代风格的工厂
modernFactory := &ModernFactory{}
modernCircle := modernFactory.CreateCircle()
modernCircle.Draw()
// 创建经典风格的工厂
classicFactory := &ClassicFactory{}
classicRectangle := classicFactory.CreateRectangle()
classicRectangle.Draw()
}核心概念
- Shape 接口定义了
Draw方法。 - ModernCircle、ClassicCircle、ModernRectangle、ClassicRectangle 是不同风格的具体产品。
- ShapeFactory 是抽象工厂接口,定义了
CreateCircle和CreateRectangle方法。 - ModernFactory 和 ClassicFactory 是具体的工厂类,分别创建不同风格的产品。
工厂模式的优缺点
优点:
- 封装对象创建过程:
- 客户端不需要了解产品的具体创建过程,只需要调用工厂方法。
- 便于扩展:
- 新的产品类型可以通过添加新的工厂类来扩展,符合开闭原则。
- 隔离复杂的创建过程:
- 工厂方法将复杂的对象创建过程抽象出来,减少客户端的复杂性。
缺点:
- 增加代码量:
- 每增加一个新的产品类型,就需要创建一个新的工厂类,导致代码量增加。
- 不灵活:
- 如果产品类之间的差异较小,工厂方法模式可能导致过多的冗余代码。
总结
工厂模式提供了创建对象的灵活性,通过将对象的创建过程抽象出来,可以使客户端代码解耦,便于扩展和维护。在 Go 中,工厂模式能够利用接口、结构体和方法的组合来实现强大的灵活性和可扩展性。