工厂模式

创建型模式

访问次数: 26

工厂模式定义了一个创建对象的接口,但让子类决定实例化哪个类。工厂方法让类的实例化推迟到子类。

类图
classDiagram
    class Product {
        <<interface>>
        +operation()
    }
    class ConcreteProductA {
        +operation()
    }
    class ConcreteProductB {
        +operation()
    }
    class Creator {
        <<abstract>>
        +factoryMethod() Product
        +someOperation()
    }
    class ConcreteCreatorA {
        +factoryMethod() Product
    }
    class ConcreteCreatorB {
        +factoryMethod() Product
    }
    Product <|-- ConcreteProductA
    Product <|-- ConcreteProductB
    Creator <|-- ConcreteCreatorA
    Creator <|-- ConcreteCreatorB
    ConcreteCreatorA --> ConcreteProductA
    ConcreteCreatorB --> ConcreteProductB
源代码示例
// 产品接口
interface Product {
    void operation();
}

// 具体产品A
class ConcreteProductA implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductA operation");
    }
}

// 具体产品B
class ConcreteProductB implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductB operation");
    }
}

// 抽象创建者
abstract class Creator {
    public abstract Product factoryMethod();
    
    public void someOperation() {
        Product product = factoryMethod();
        product.operation();
    }
}

// 具体创建者A
class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

// 具体创建者B
class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}
# 产品接口(抽象基类)
from abc import ABC, abstractmethod

class Product(ABC):
    @abstractmethod
    def operation(self):
        pass

# 具体产品A
class ConcreteProductA(Product):
    def operation(self):
        print("ConcreteProductA operation")

# 具体产品B
class ConcreteProductB(Product):
    def operation(self):
        print("ConcreteProductB operation")

# 抽象创建者
class Creator(ABC):
    @abstractmethod
    def factory_method(self):
        pass
    
    def some_operation(self):
        product = self.factory_method()
        product.operation()

# 具体创建者A
class ConcreteCreatorA(Creator):
    def factory_method(self):
        return ConcreteProductA()

# 具体创建者B
class ConcreteCreatorB(Creator):
    def factory_method(self):
        return ConcreteProductB()

# 使用示例
if __name__ == "__main__":
    creator_a = ConcreteCreatorA()
    creator_b = ConcreteCreatorB()
    
    creator_a.some_operation()
    creator_b.some_operation()
应用场景
当需要创建的对象类型在运行时确定,或者需要将对象创建与使用分离时。应用场景包括: 1)文档处理系统中,根据文件类型创建不同的解析器(PDF解析器、Word解析器、Excel解析器) 2)游戏开发中根据角色类型创建不同的角色对象(战士、法师、弓箭手) 3)消息队列系统中根据消息类型创建不同的消息处理器(邮件处理器、短信处理器、推送处理器) 4)电商系统中根据商品类型创建不同的商品展示组件(图书展示、服装展示、电子产品展示) 5)多媒体播放器中根据文件格式创建不同的解码器(MP3解码器、MP4解码器、AVI解码器)
精选场景详解 —— 文档处理:按文件类型创建解析器
问题背景

文档平台要支持 PDF、Word、Excel 等格式。若在业务里硬编码解析器类型,扩展新格式时会牵动多处调用代码,也难做到「解析器实现可替换」。

模式如何解决
选用工厂方法模式:定义抽象 Creator(DocumentParserCreator)声明 factoryMethod,由 ConcreteCreator(PdfParserCreator、WordParserCreator 等)决定实例化哪种解析器。 与简单工厂的区别: - 简单工厂:一个工厂类用分支创建所有产品; - 工厂方法:创建职责下沉到子类,符合开闭原则,扩展新格式时新增 Creator/Product,少改已有类。 客户端依赖 Creator 抽象,调用 someOperation/parse 流程,无需知道具体解析器类名。适合「产品种类会持续增加」的文档系统。
场景模型(角色映射)

将模式中的抽象角色映射到该业务领域的具体类:

classDiagram
    class DocumentParser {
        <<interface>>
        +parse(path: String) Document
    }
    class PdfParser {
        +parse(path: String) Document
    }
    class WordParser {
        +parse(path: String) Document
    }
    class ExcelParser {
        +parse(path: String) Document
    }
    class ParserCreator {
        <<abstract>>
        +factoryMethod() DocumentParser
        +importFile(path: String) Document
    }
    class PdfParserCreator {
        +factoryMethod() DocumentParser
    }
    class WordParserCreator {
        +factoryMethod() DocumentParser
    }
    DocumentParser <|.. PdfParser
    DocumentParser <|.. WordParser
    DocumentParser <|.. ExcelParser
    ParserCreator <|-- PdfParserCreator
    ParserCreator <|-- WordParserCreator
    PdfParserCreator --> PdfParser
    WordParserCreator --> WordParser
    ParserCreator --> DocumentParser