工厂方法模式详解:原理、实现与应用场景

📅 2026/8/12 12:32:42
工厂方法模式详解:原理、实现与应用场景
1. 工厂方法模式的核心思想工厂方法模式Factory Method是一种创建型设计模式它定义了一个用于创建对象的接口但让子类决定实例化哪一个类。这种模式的核心在于将对象的实例化过程推迟到子类中进行而不是在父类中直接实例化具体类。想象一下你去餐厅点餐的场景。当你点一份披萨时服务员客户端并不需要知道披萨具体是如何制作的他只需要把订单交给厨房工厂。而厨房会根据订单类型决定是制作意大利披萨还是美式披萨。这个厨房就是我们的工厂方法它封装了对象创建的复杂性。工厂方法模式主要解决以下问题一个类无法预知它需要创建哪个类的对象一个类希望由其子类来指定它所创建的对象需要将创建对象的职责委托给多个帮助子类中的某一个2. 工厂方法模式的结构解析2.1 模式参与者工厂方法模式通常包含以下几个关键角色Product抽象产品定义工厂方法所创建的对象的接口ConcreteProduct具体产品实现Product接口的具体类Creator抽象创建者声明工厂方法该方法返回一个Product类型的对象ConcreteCreator具体创建者重写工厂方法以返回一个ConcreteProduct实例2.2 UML类图表示[Creator] |___ factoryMethod(): Product |___ anOperation() [ConcreteCreator] |___ factoryMethod(): Product [Product] |___ interface() [ConcreteProduct] |___ interface()2.3 代码示例结构// 抽象产品 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 { // 工厂方法 abstract Product factoryMethod(); public void anOperation() { Product product factoryMethod(); product.operation(); } } // 具体创建者A class ConcreteCreatorA extends Creator { Override Product factoryMethod() { return new ConcreteProductA(); } } // 具体创建者B class ConcreteCreatorB extends Creator { Override Product factoryMethod() { return new ConcreteProductB(); } }3. 工厂方法模式的实现细节3.1 参数化工厂方法工厂方法可以有多种变体其中一种常见的是参数化工厂方法。在这种变体中工厂方法接收一个参数根据这个参数决定创建哪种产品。abstract class Creator { // 参数化工厂方法 abstract Product factoryMethod(String type); } class ConcreteCreator extends Creator { Override Product factoryMethod(String type) { switch (type) { case A: return new ConcreteProductA(); case B: return new ConcreteProductB(); default: throw new IllegalArgumentException(Unknown product type); } } }3.2 使用类对象作为工厂方法参数在Java等支持反射的语言中可以使用Class对象作为工厂方法的参数abstract class Creator { abstract Product factoryMethod(Class? extends Product productClass); } class ConcreteCreator extends Creator { Override Product factoryMethod(Class? extends Product productClass) { try { return productClass.newInstance(); } catch (Exception e) { throw new RuntimeException(Failed to create product, e); } } }3.3 工厂方法模式与简单工厂的区别很多初学者容易混淆工厂方法模式和简单工厂模式。它们的核心区别在于简单工厂由一个工厂类根据传入的参数决定创建哪种产品工厂方法定义一个创建对象的接口让子类决定实例化哪个类简单工厂把全部创建逻辑集中在一个类中而工厂方法则将创建逻辑分散到各个子类中。4. 工厂方法模式的实际应用场景4.1 框架设计中的应用工厂方法模式在框架设计中非常常见。例如在Java的集合框架中java.util.Collection接口定义了iterator()方法这就是一个工厂方法。具体的集合类如ArrayList、HashSet实现了这个方法返回适合自己数据结构的迭代器。public interface CollectionE { IteratorE iterator(); // 其他方法... } public class ArrayListE implements CollectionE { Override public IteratorE iterator() { return new Itr(); // 返回ArrayList特有的迭代器 } // 其他实现... }4.2 跨平台UI开发在跨平台UI框架中工厂方法模式可以用来创建平台特定的UI组件。例如// 抽象产品按钮 interface Button { void render(); void onClick(); } // 具体产品Windows按钮 class WindowsButton implements Button { Override public void render() { System.out.println(Render Windows style button); } Override public void onClick() { System.out.println(Windows button clicked); } } // 具体产品MacOS按钮 class MacOSButton implements Button { Override public void render() { System.out.println(Render MacOS style button); } Override public void onClick() { System.out.println(MacOS button clicked); } } // 抽象创建者 abstract class Dialog { abstract Button createButton(); public void render() { Button button createButton(); button.render(); button.onClick(); } } // 具体创建者Windows对话框 class WindowsDialog extends Dialog { Override Button createButton() { return new WindowsButton(); } } // 具体创建者MacOS对话框 class MacOSDialog extends Dialog { Override Button createButton() { return new MacOSButton(); } }4.3 数据库访问层在数据库访问层中工厂方法可以用来创建不同类型的数据库连接interface Connection { void connect(); void executeQuery(String query); } class MySQLConnection implements Connection { Override public void connect() { System.out.println(Connecting to MySQL database); } Override public void executeQuery(String query) { System.out.println(Executing MySQL query: query); } } class OracleConnection implements Connection { Override public void connect() { System.out.println(Connecting to Oracle database); } Override public void executeQuery(String query) { System.out.println(Executing Oracle query: query); } } abstract class ConnectionFactory { abstract Connection createConnection(); } class MySQLConnectionFactory extends ConnectionFactory { Override Connection createConnection() { return new MySQLConnection(); } } class OracleConnectionFactory extends ConnectionFactory { Override Connection createConnection() { return new OracleConnection(); } }5. 工厂方法模式的优缺点分析5.1 优势松耦合客户端代码只需要知道抽象产品接口不需要关心具体实现类可扩展性添加新产品时只需添加新的具体工厂类无需修改现有代码单一职责原则将产品创建逻辑集中在一个地方便于维护开闭原则对扩展开放可以引入新的产品类型对修改关闭不需要修改现有代码5.2 局限性类数量增加每增加一个产品通常需要增加一个具体工厂类抽象性增加需要引入额外的抽象层增加了系统的复杂度客户端必须知道具体工厂类虽然客户端不需要知道具体产品类但它需要知道使用哪个具体工厂类5.3 适用场景评估工厂方法模式特别适用于以下场景一个类无法预知它必须创建的对象的类一个类希望由其子类来指定它所创建的对象需要将类的实例化延迟到子类中需要提供灵活的、可扩展的对象创建机制6. 工厂方法模式的变体与扩展6.1 并行类层次结构工厂方法模式常常与并行类层次结构一起使用。在这种结构中一个类层次结构中的类在另一个类层次结构中具有对应的工厂类。[Shape] [ShapeFactory] |___ [Circle] |___ [CircleFactory] |___ [Rectangle] |___ [RectangleFactory] |___ [Triangle] |___ [TriangleFactory]6.2 模板方法模式与工厂方法模式的结合工厂方法模式经常与模板方法模式结合使用。模板方法定义算法的骨架而将某些步骤的实现推迟到子类中。工厂方法可以作为这些推迟步骤的一种实现方式。abstract class Application { // 模板方法 public final void run() { Document doc createDocument(); // 工厂方法 doc.open(); doc.save(); doc.close(); } // 工厂方法 abstract Document createDocument(); } class WordProcessor extends Application { Override Document createDocument() { return new WordDocument(); } } class Spreadsheet extends Application { Override Document createDocument() { return new SpreadsheetDocument(); } }6.3 使用Lambda表达式简化工厂方法在Java 8及更高版本中可以使用Lambda表达式或方法引用来简化工厂方法的实现interface ProductFactory { Product create(); } public class Client { private static final MapString, ProductFactory factories new HashMap(); static { factories.put(A, ConcreteProductA::new); factories.put(B, ConcreteProductB::new); } public static Product createProduct(String type) { ProductFactory factory factories.get(type); if (factory null) { throw new IllegalArgumentException(Unknown product type); } return factory.create(); } }7. 工厂方法模式的最佳实践7.1 设计考虑事项工厂方法的访问级别通常声明为protected这样只有子类可以重写它空工厂方法有时可以提供一个默认实现返回null或默认对象参数化工厂方法当需要基于不同条件创建不同对象时很有用命名约定工厂方法通常命名为createXXX()或newXXX()7.2 性能考量虽然工厂方法模式提供了灵活性但在性能敏感的场景中需要注意对象创建开销频繁创建对象可能影响性能考虑使用对象池反射开销如果使用反射实现工厂方法要注意反射的性能影响缓存机制对于创建成本高的对象可以在工厂中实现缓存7.3 测试策略工厂方法模式使得单元测试更加容易产品接口测试可以针对抽象产品接口编写测试模拟对象在测试客户端代码时可以轻松注入模拟产品工厂子类测试每个具体工厂可以单独测试其创建的产品// 测试示例 Test public void testConcreteCreatorA() { Creator creator new ConcreteCreatorA(); Product product creator.factoryMethod(); assertTrue(product instanceof ConcreteProductA); } Test public void testProductOperation() { Product product new ConcreteProductA(); product.operation(); // 验证操作结果 }8. 工厂方法模式与其他模式的比较8.1 工厂方法 vs 抽象工厂工厂方法模式和抽象工厂模式都用于创建对象但它们有不同的侧重点工厂方法创建单一产品通过子类化来决定具体实例抽象工厂创建产品家族不需要子类化工厂方法通常用于单个产品的创建而抽象工厂用于创建相关或依赖对象的家族。8.2 工厂方法 vs 建造者模式工厂方法和建造者模式都创建对象但它们的关注点不同工厂方法关注的是创建什么对象what建造者模式关注的是如何创建复杂对象how工厂方法通常用于创建单一、相对简单的对象而建造者模式用于创建具有多个部分的复杂对象。8.3 工厂方法 vs 原型模式工厂方法和原型模式都是创建型模式但它们的实现方式不同工厂方法通过子类化来创建新对象原型模式通过克隆现有对象来创建新对象原型模式适用于创建成本高的对象或者需要避免使用new关键字的情况。9. 工厂方法模式在实际项目中的经验分享9.1 避免过度设计虽然工厂方法模式提供了灵活性但并不是所有情况都需要使用它。在实际项目中应该根据以下标准决定是否使用工厂方法对象创建逻辑是否复杂或可能变化是否需要支持多种产品类型系统是否需要独立于其产品的创建、组合和表示如果答案都是否那么可能简单直接的new操作符就足够了。9.2 处理产品初始化工厂方法不仅负责创建对象还可以负责初始化对象。这是一个常见的实践abstract class Creator { abstract Product factoryMethod(); protected void initializeProduct(Product product) { // 默认初始化逻辑 product.setDefaultConfig(); } } class ConcreteCreator extends Creator { Override Product factoryMethod() { Product product new ConcreteProduct(); initializeProduct(product); product.setSpecificConfig(); // 特定初始化 return product; } }9.3 处理创建异常对象创建可能会失败工厂方法应该妥善处理这些异常情况abstract class Creator { abstract Product factoryMethod() throws ProductCreationException; } class ConcreteCreator extends Creator { Override Product factoryMethod() throws ProductCreationException { try { return new ConcreteProduct(); } catch (Exception e) { throw new ProductCreationException(Failed to create product, e); } } }9.4 日志和监控在工厂方法中添加适当的日志和监控可以帮助调试和性能分析abstract class Creator { private static final Logger logger LoggerFactory.getLogger(Creator.class); abstract Product factoryMethod(); public Product create() { long startTime System.currentTimeMillis(); Product product factoryMethod(); long duration System.currentTimeMillis() - startTime; logger.debug(Created {} in {} ms, product.getClass().getSimpleName(), duration); monitorCreation(product.getClass(), duration); return product; } protected abstract void monitorCreation(Class? extends Product productClass, long duration); }10. 工厂方法模式的现代应用10.1 在依赖注入框架中的应用现代依赖注入DI框架如Spring、Guice等广泛使用了工厂方法的概念。例如Spring中的Bean注解实际上就是声明了一个工厂方法Configuration public class AppConfig { Bean public DataSource dataSource() { // 工厂方法实现 return new HikariDataSource(); } }10.2 在函数式编程中的应用在函数式编程中工厂方法可以表示为高阶函数// JavaScript示例 function createProductFactory(productType) { switch (productType) { case A: return () new ProductA(); case B: return () new ProductB(); default: throw new Error(Unknown product type); } } const factoryA createProductFactory(A); const productA factoryA();10.3 在微服务架构中的应用在微服务架构中工厂方法模式可以用于创建不同类型的服务客户端interface ServiceClient { void callService(); } class RestServiceClient implements ServiceClient { Override public void callService() { // REST调用实现 } } class GrpcServiceClient implements ServiceClient { Override public void callService() { // gRPC调用实现 } } interface ServiceClientFactory { ServiceClient createClient(); } class RestServiceClientFactory implements ServiceClientFactory { Override public ServiceClient createClient() { return new RestServiceClient(); } } class GrpcServiceClientFactory implements ServiceClientFactory { Override public ServiceClient createClient() { return new GrpcServiceClient(); } }11. 工厂方法模式的替代方案虽然工厂方法模式非常有用但在某些情况下其他方法可能更合适11.1 服务定位器模式当对象创建需要从外部配置或运行时决定时服务定位器模式可能是更好的选择class ServiceLocator { private static final MapString, SupplierProduct factories new HashMap(); static { register(A, ConcreteProductA::new); register(B, ConcreteProductB::new); } public static void register(String type, SupplierProduct factory) { factories.put(type, factory); } public static Product create(String type) { SupplierProduct factory factories.get(type); if (factory null) { throw new IllegalArgumentException(Unknown product type); } return factory.get(); } }11.2 依赖注入在大型应用程序中依赖注入通常比直接使用工厂方法更灵活class Client { private final Product product; Inject public Client(Product product) { this.product product; } public void doSomething() { product.operation(); } }11.3 静态工厂方法有时简单的静态工厂方法就足够了class ProductFactory { public static Product createProduct(String type) { switch (type) { case A: return new ConcreteProductA(); case B: return new ConcreteProductB(); default: throw new IllegalArgumentException(Unknown product type); } } }12. 工厂方法模式的性能优化12.1 对象池技术对于创建成本高的对象可以结合对象池技术abstract class PooledCreator { private final QueueProduct pool new LinkedList(); abstract Product createNew(); public Product getProduct() { if (pool.isEmpty()) { return createNew(); } return pool.poll(); } public void releaseProduct(Product product) { pool.offer(product); } }12.2 延迟初始化对于不总是需要的产品可以实现延迟初始化abstract class LazyCreator { private Product product; abstract Product createProduct(); public Product getProduct() { if (product null) { product createProduct(); } return product; } }12.3 缓存策略缓存已创建的产品可以提高性能abstract class CachingCreator { private final MapString, Product cache new HashMap(); abstract Product createProduct(String key); public Product getProduct(String key) { return cache.computeIfAbsent(key, this::createProduct); } }13. 工厂方法模式的反模式与常见错误13.1 过度使用工厂方法不是所有对象创建都需要使用工厂方法。过度使用会导致代码复杂化增加维护成本。13.2 违反单一职责原则如果工厂方法不仅创建对象还包含复杂的业务逻辑就违反了单一职责原则。13.3 忽略异常处理工厂方法应该妥善处理对象创建过程中可能出现的异常而不是简单地抛出运行时异常。13.4 循环依赖当具体工厂和具体产品之间存在循环依赖时会导致设计问题。应该通过重构来消除这种循环。14. 工厂方法模式的演进与未来14.1 在云原生应用中的演变在云原生和Serverless架构中工厂方法模式演变为更动态的对象提供方式如通过服务网格或函数即服务FaaS来实现。14.2 与容器技术的结合现代容器技术如Docker和编排系统如Kubernetes可以被视为更高层次的工厂方法实现它们动态地创建和管理服务实例。14.3 在AI和机器学习中的应用在机器学习系统中工厂方法模式可以用于创建不同类型的模型或处理器根据输入数据动态选择最合适的实现。15. 工厂方法模式的代码重构技巧15.1 将构造器替换为工厂方法当发现直接使用构造器不够灵活时可以重构为工厂方法重构前class Client { private Product product; public Client(String type) { if (A.equals(type)) { product new ProductA(); } else { product new ProductB(); } } }重构后class Client { private Product product; public Client(Product product) { this.product product; } // 静态工厂方法 public static Client create(String type) { Product product; if (A.equals(type)) { product new ProductA(); } else { product new ProductB(); } return new Client(product); } }15.2 将简单工厂升级为工厂方法当简单工厂变得难以维护时可以升级为工厂方法重构前class ProductFactory { public static Product createProduct(String type) { switch (type) { case A: return new ProductA(); case B: return new ProductB(); default: throw new IllegalArgumentException(); } } }重构后interface ProductFactory { Product createProduct(); } class ProductAFactory implements ProductFactory { Override public Product createProduct() { return new ProductA(); } } class ProductBFactory implements ProductFactory { Override public Product createProduct() { return new ProductB(); } }15.3 合并相似的工厂方法当发现多个工厂方法逻辑相似时可以考虑合并重构前class CreatorA { Product createProduct() { return new ProductA(); } } class CreatorB { Product createProduct() { return new ProductB(); } }重构后使用参数化工厂方法class UnifiedCreator { Product createProduct(String type) { switch (type) { case A: return new ProductA(); case B: return new ProductB(); default: throw new IllegalArgumentException(); } } }16. 工厂方法模式在不同语言中的实现差异16.1 Java中的实现Java中的工厂方法通常使用抽象类和接口来实现// 使用抽象类 abstract class Creator { abstract Product factoryMethod(); } // 使用接口 interface Creator { Product factoryMethod(); }16.2 Python中的实现Python的鸭子类型使得工厂方法的实现更加灵活from abc import ABC, abstractmethod class Creator(ABC): abstractmethod def factory_method(self): pass def some_operation(self): product self.factory_method() return fCreator: {product.operation()} class ConcreteCreator1(Creator): def factory_method(self): return ConcreteProduct1() class ConcreteProduct1: def operation(self): return Result of ConcreteProduct116.3 JavaScript/TypeScript中的实现JavaScript可以使用函数或类来实现工厂方法// 使用类 class Creator { factoryMethod() { throw new Error(factoryMethod must be implemented); } } class ConcreteCreator extends Creator { factoryMethod() { return new ConcreteProduct(); } } // 使用函数 function createProduct(type) { const creators { A: () new ProductA(), B: () new ProductB() }; const creator creators[type]; if (!creator) { throw new Error(Unknown product type: ${type}); } return creator(); }16.4 C中的实现C中的工厂方法通常使用虚函数class Product { public: virtual ~Product() {} virtual std::string Operation() const 0; }; class Creator { public: virtual ~Creator() {}; virtual Product* FactoryMethod() const 0; std::string SomeOperation() const { Product* product this-FactoryMethod(); std::string result Creator: product-Operation(); delete product; return result; } }; class ConcreteCreator : public Creator { public: Product* FactoryMethod() const override { return new ConcreteProduct(); } };17. 工厂方法模式的测试策略17.1 单元测试工厂方法测试工厂方法是否返回正确的产品类型Test public void testConcreteCreatorAFactoryMethod() { Creator creator new ConcreteCreatorA(); Product product creator.factoryMethod(); assertTrue(product instanceof ConcreteProductA); }17.2 集成测试产品使用测试工厂创建的产品在实际使用中的行为Test public void testProductOperation() { Creator creator new ConcreteCreatorA(); Product product creator.factoryMethod(); String result product.operation(); assertEquals(Expected result, result); }17.3 性能测试测试工厂方法的性能特别是当创建过程复杂时Test public void testFactoryMethodPerformance() { Creator creator new ConcreteCreatorA(); long startTime System.nanoTime(); for (int i 0; i 1000; i) { creator.factoryMethod(); } long duration System.nanoTime() - startTime; assertTrue(duration TimeUnit.SECONDS.toNanos(1)); }17.4 模拟测试使用模拟对象测试依赖于工厂方法的客户端代码Test public void testClientWithMockProduct() { Product mockProduct mock(Product.class); when(mockProduct.operation()).thenReturn(Mock result); Creator mockCreator mock(Creator.class); when(mockCreator.factoryMethod()).thenReturn(mockProduct); Client client new Client(mockCreator); String result client.doSomething(); assertEquals(Mock result, result); }18. 工厂方法模式的文档化建议18.1 类图文档为工厂方法模式创建清晰的类图展示各个角色及其关系。18.2 序列图文档绘制序列图展示客户端如何通过工厂方法获取和使用产品[Client] - [Creator] : factoryMethod() [Creator] - [ConcreteProduct] : new() [Creator] -- [Client] : Product [Client] - [Product] : operation()18.3 使用示例文档提供完整的代码示例展示如何实现和使用工厂方法模式// 示例代码展示如何创建和使用工厂 Creator creator new ConcreteCreatorA(); Product product creator.factoryMethod(); product.operation();18.4 模式选择理由文档在文档中说明为什么选择工厂方法模式而不是其他创建型模式。19. 工厂方法模式在开源项目中的应用实例19.1 Java集合框架中的IteratorJava集合框架中的iterator()方法是一个典型的工厂方法ListString list new ArrayList(); IteratorString iterator list.iterator(); // 工厂方法19.2 Spring框架中的BeanFactorySpring框架的BeanFactory接口及其实现使用了工厂方法的概念public interface BeanFactory { Object getBean(String name) throws BeansException; // 其他方法... }19.3 JUnit中的TestRuleJUnit中的TestRule接口及其实现也使用了工厂方法模式public interface TestRule { Statement apply(Statement base, Description description); } public class TemporaryFolder implements TestRule { Override public Statement apply(Statement base, Description description) { return new Statement() { Override public void evaluate() throws Throwable { // 实现逻辑 } }; } }19.4 React中的组件工厂在React中组件可以看作产品而组件工厂用于创建这些组件function createComponent(type) { switch (type) { case button: return Button; case input: return Input; default: throw new Error(Unknown component type: ${type}); } } const Component createComponent(button); return Component /;20. 工厂方法模式的进阶思考20.1 工厂方法与控制反转工厂方法模式是实现控制反转IoC的一种方式。它将对象创建的主动权从客户端转移到工厂中。20.2 工厂方法与依赖注入依赖注入DI可以看作是工厂方法模式的一种演进。DI容器本质上是一个超级工厂负责创建和管理所有对象。20.3 工厂方法与领域驱动设计在领域驱动设计DDD中工厂方法模式可以用于实现领域对象的创建逻辑保持领域模型的纯净性。20.4 工厂方法与微服务架构在微服务架构中服务客户端工厂可以根据服务发现机制动态创建适当的客户端实现。20.5 工厂方法与函数式编程在函数式编程中工厂方法可以表现为高阶函数接收参数并返回特定的函数实现。