设计模式解密:工厂模式的终极指南(PHP/Go双实现)
一、什么是工厂模式?
工厂模式(Factory Pattern) 是一种创建型设计模式,它提供了一种创建对象的方式,而无需指定具体的类。工厂模式的核心思想是将对象的创建逻辑与使用逻辑分离,从而提高代码的灵活性和可维护性。
核心特征:
封装创建逻辑:将对象的创建过程封装在工厂类中。
解耦客户端代码:客户端无需知道具体类的实现细节。
支持扩展:新增产品类时,无需修改客户端代码。
二、适用场景
✅ 需要创建复杂对象(如数据库连接、日志记录器)
✅ 需要根据条件动态创建对象
✅ 需要解耦客户端代码与具体类
✅ 需要支持多种产品族的扩展
三、工厂模式的三种形式
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"
}
六、关键实现差异对比
七、模式优缺点分析
👍 优点:
解耦创建逻辑:将对象的创建与使用分离。
支持扩展:新增产品类时,无需修改客户端代码。
提高可维护性:集中管理对象的创建逻辑。
👎 缺点:
增加复杂度:引入额外的类和接口。
过度设计:简单场景下可能显得冗余。
八、实际应用案例
1. 数据库连接工厂
根据配置创建MySQL、PostgreSQL等连接对象。
2. 日志记录器工厂
根据环境创建文件日志、控制台日志等记录器。
3. UI组件工厂
根据操作系统创建不同风格的UI组件。
九、总结
工厂模式是解决对象创建问题的经典设计模式。通过将对象的创建逻辑封装在工厂类中,我们可以实现代码的解耦、扩展和维护。无论是PHP还是Go,工厂模式都能显著提升代码的灵活性和可读性。
在下一篇文章中,我们将深入探讨 抽象工厂模式 及其在复杂系统中的应用。敬请期待!
下一篇预告:设计模式系列(三)——抽象工厂模式:构建复杂对象族的艺术
License:
CC BY 4.0