文章

设计模式解密:工厂模式的终极指南(PHP/Go双实现)

一、什么是工厂模式?

工厂模式(Factory Pattern) 是一种创建型设计模式,它提供了一种创建对象的方式,而无需指定具体的类。工厂模式的核心思想是将对象的创建逻辑与使用逻辑分离,从而提高代码的灵活性和可维护性。

核心特征:

  1. 封装创建逻辑:将对象的创建过程封装在工厂类中。

  2. 解耦客户端代码:客户端无需知道具体类的实现细节。

  3. 支持扩展:新增产品类时,无需修改客户端代码。

工厂模式结构图


二、适用场景

  • ✅ 需要创建复杂对象(如数据库连接、日志记录器)

  • ✅ 需要根据条件动态创建对象

  • ✅ 需要解耦客户端代码与具体类

  • ✅ 需要支持多种产品族的扩展


三、工厂模式的三种形式

1. 简单工厂模式

  • 一个工厂类负责创建所有产品。

  • 适用于产品种类较少且固定的场景。

2. 工厂方法模式

  • 每个产品对应一个工厂类。

  • 适用于产品种类较多且可能扩展的场景。

3. 抽象工厂模式

  • 提供一个创建一系列相关或依赖对象的接口。

  • 适用于需要创建多个产品族的场景。


四、PHP实现方案

1. 简单工厂模式

interface Product {
    public function getName(): string;
}

class ProductA implements Product {
    public function getName(): string {
        return "Product A";
    }
}

class ProductB implements Product {
    public function getName(): string {
        return "Product B";
    }
}

class SimpleFactory {
    public static function createProduct(string $type): Product {
        switch ($type) {
            case 'A':
                return new ProductA();
            case 'B':
                return new ProductB();
            default:
                throw new InvalidArgumentException("Unknown product type");
        }
    }
}

// 使用示例
$product = SimpleFactory::createProduct('A');
echo $product->getName(); // 输出 "Product A"

2. 工厂方法模式

interface Product {
    public function getName(): string;
}

class ProductA implements Product {
    public function getName(): string {
        return "Product A";
    }
}

class ProductB implements Product {
    public function getName(): string {
        return "Product B";
    }
}

interface Factory {
    public function createProduct(): Product;
}

class FactoryA implements Factory {
    public function createProduct(): Product {
        return new ProductA();
    }
}

class FactoryB implements Factory {
    public function createProduct(): Product {
        return new ProductB();
    }
}

// 使用示例
$factory = new FactoryA();
$product = $factory->createProduct();
echo $product->getName(); // 输出 "Product A"

3. 抽象工厂模式

interface Button {
    public function render(): string;
}

interface Checkbox {
    public function render(): string;
}

class WindowsButton implements Button {
    public function render(): string {
        return "Render a button in Windows style";
    }
}

class WindowsCheckbox implements Checkbox {
    public function render(): string {
        return "Render a checkbox in Windows style";
    }
}

class MacButton implements Button {
    public function render(): string {
        return "Render a button in Mac style";
    }
}

class MacCheckbox implements Checkbox {
    public function render(): string {
        return "Render a checkbox in Mac style";
    }
}

interface GUIFactory {
    public function createButton(): Button;
    public function createCheckbox(): Checkbox;
}

class WindowsFactory implements GUIFactory {
    public function createButton(): Button {
        return new WindowsButton();
    }

    public function createCheckbox(): Checkbox {
        return new WindowsCheckbox();
    }
}

class MacFactory implements GUIFactory {
    public function createButton(): Button {
        return new MacButton();
    }

    public function createCheckbox(): Checkbox {
        return new MacCheckbox();
    }
}

// 使用示例
$factory = new MacFactory();
$button = $factory->createButton();
$checkbox = $factory->createCheckbox();
echo $button->render(); // 输出 "Render a button in Mac style"
echo $checkbox->render(); // 输出 "Render a checkbox in Mac style"

五、Go实现方案

1. 简单工厂模式

package main

import (
    "errors"
    "fmt"
)

type Product interface {
    GetName() string
}

type ProductA struct{}

func (p ProductA) GetName() string {
    return "Product A"
}

type ProductB struct{}

func (p ProductB) GetName() string {
    return "Product B"
}

func CreateProduct(productType string) (Product, error) {
    switch productType {
    case "A":
        return ProductA{}, nil
    case "B":
        return ProductB{}, nil
    default:
        return nil, errors.New("unknown product type")
    }
}

func main() {
    product, _ := CreateProduct("A")
    fmt.Println(product.GetName()) // 输出 "Product A"
}

2. 工厂方法模式

package main

import "fmt"

type Product interface {
    GetName() string
}

type ProductA struct{}

func (p ProductA) GetName() string {
    return "Product A"
}

type ProductB struct{}

func (p ProductB) GetName() string {
    return "Product B"
}

type Factory interface {
    CreateProduct() Product
}

type FactoryA struct{}

func (f FactoryA) CreateProduct() Product {
    return ProductA{}
}

type FactoryB struct{}

func (f FactoryB) CreateProduct() Product {
    return ProductB{}
}

func main() {
    factory := FactoryA{}
    product := factory.CreateProduct()
    fmt.Println(product.GetName()) // 输出 "Product A"
}

3. 抽象工厂模式

package main

import "fmt"

type Button interface {
    Render() string
}

type Checkbox interface {
    Render() string
}

type WindowsButton struct{}

func (b WindowsButton) Render() string {
    return "Render a button in Windows style"
}

type WindowsCheckbox struct{}

func (c WindowsCheckbox) Render() string {
    return "Render a checkbox in Windows style"
}

type MacButton struct{}

func (b MacButton) Render() string {
    return "Render a button in Mac style"
}

type MacCheckbox struct{}

func (c MacCheckbox) Render() string {
    return "Render a checkbox in Mac style"
}

type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

type WindowsFactory struct{}

func (f WindowsFactory) CreateButton() Button {
    return WindowsButton{}
}

func (f WindowsFactory) CreateCheckbox() Checkbox {
    return WindowsCheckbox{}
}

type MacFactory struct{}

func (f MacFactory) CreateButton() Button {
    return MacButton{}
}

func (f MacFactory) CreateCheckbox() Checkbox {
    return MacCheckbox{}
}

func main() {
    factory := MacFactory{}
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render())   // 输出 "Render a button in Mac style"
    fmt.Println(checkbox.Render()) // 输出 "Render a checkbox in Mac style"
}

六、关键实现差异对比

特性

PHP

Go

接口定义

使用interface关键字

使用interface关键字

多态支持

通过接口实现

通过接口实现

错误处理

使用try-catch

使用error返回值

工厂方法

支持静态方法

不支持静态方法

依赖注入

可通过容器实现

需手动实现


七、模式优缺点分析

👍 优点:

  • 解耦创建逻辑:将对象的创建与使用分离。

  • 支持扩展:新增产品类时,无需修改客户端代码。

  • 提高可维护性:集中管理对象的创建逻辑。

👎 缺点:

  • 增加复杂度:引入额外的类和接口。

  • 过度设计:简单场景下可能显得冗余。


八、实际应用案例

1. 数据库连接工厂

  • 根据配置创建MySQL、PostgreSQL等连接对象。

2. 日志记录器工厂

  • 根据环境创建文件日志、控制台日志等记录器。

3. UI组件工厂

  • 根据操作系统创建不同风格的UI组件。


九、总结

工厂模式是解决对象创建问题的经典设计模式。通过将对象的创建逻辑封装在工厂类中,我们可以实现代码的解耦、扩展和维护。无论是PHP还是Go,工厂模式都能显著提升代码的灵活性和可读性。

在下一篇文章中,我们将深入探讨 抽象工厂模式 及其在复杂系统中的应用。敬请期待!


下一篇预告:设计模式系列(三)——抽象工厂模式:构建复杂对象族的艺术

License:  CC BY 4.0