工厂模式是一种创建型设计模式,其核心思想是定义一个创建对象的接口(即工厂),让子类决定实例化哪一个类。工厂模式将对象的创建与使用分离,使代码更易于维护和扩展,尤其在需要根据条件动态创建不同类的实例时非常有用。
工厂模式主要有以下三种形态:
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
- // 定义产品接口
- public interface Product {
- void use();
- }
-
- // 具体产品A
- public class ConcreteProductA implements Product {
- @Override
- public void use() {
- System.out.println("Using product A");
- }
- }
-
- // 具体产品B
- public class ConcreteProductB implements Product {
- @Override
- public void use() {
- System.out.println("Using product B");
- }
- }
-
- // 工厂类
- public class SimpleFactory {
- public static Product createProduct(String type) {
- if ("A".equals(type)) {
- return new ConcreteProductA();
- } else if ("B".equals(type)) {
- return new ConcreteProductB();
- } else {
- throw new IllegalArgumentException("Invalid product type");
- }
- }
- }
-
- // 客户端代码
- public class Client {
- public static void main(String[] args) {
- Product productA = SimpleFactory.createProduct("A");
- productA.use(); // 输出:Using product A
-
- Product productB = SimpleFactory.createProduct("B");
- productB.use(); // 输出:Using product B
- }
- }
- // 定义产品接口
- public interface Product {
- void use();
- }
-
- // 具体产品A
- public class ConcreteProductA implements Product {
- @Override
- public void use() {
- System.out.println("Using product A");
- }
- }
-
- // 具体产品B
- public class ConcreteProductB implements Product {
- @Override
- public void use() {
- System.out.println("Using product B");
- }
- }
-
- // 抽象工厂接口
- public interface Factory {
- Product createProduct();
- }
-
- // 具体工厂A
- public class ConcreteFactoryA implements Factory {
- @Override
- public Product createProduct() {
- return new ConcreteProductA();
- }
- }
-
- // 具体工厂B
- public class ConcreteFactoryB implements Factory {
- @Override
- public Product createProduct() {
- return new ConcreteProductB();
- }
- }
-
- // 客户端代码
- public class Client {
- public static void main(String[] args) {
- Factory factoryA = new ConcreteFactoryA();
- Product productA = factoryA.createProduct();
- productA.use(); // 输出:Using product A
-
- Factory factoryB = new ConcreteFactoryB();
- Product productB = factoryB.createProduct();
- productB.use(); // 输出:Using product B
- }
- }
- // 定义产品接口
- public interface ProductA {
- void useA();
- }
-
- public interface ProductB {
- void useB();
- }
-
- // 具体产品A1
- public class ConcreteProductA1 implements ProductA {
- @Override
- public void useA() {
- System.out.println("Using product A1");
- }
- }
-
- // 具体产品B1
- public class ConcreteProductB1 implements ProductB {
- @Override
- public void useB() {
- System.out.println("Using product B1");
- }
- }
-
- // 具体产品A2
- public class ConcreteProductA2 implements ProductA {
- @Override
- public void useA() {
- System.out.println("Using product A2");
- }
- }
-
- // 具体产品B2
- public class ConcreteProductB2 implements ProductB {
- @Override
- public void useB() {
- System.out.println("Using product B2");
- }
- }
-
- // 抽象工厂接口
- public interface AbstractFactory {
- ProductA createProductA();
- ProductB createProductB();
- }
-
- // 具体工厂1
- public class ConcreteFactory1 implements AbstractFactory {
- @Override
- public ProductA createProductA() {
- return new ConcreteProductA1();
- }
-
- @Override
- public ProductB createProductB() {
- return new ConcreteProductB1();
- }
- }
-
- // 具体工厂2
- public class ConcreteFactory2 implements AbstractFactory {
- @Override
- public ProductA createProductA() {
- return new ConcreteProductA2();
- }
-
- @Override
- public ProductB createProductB() {
- return new ConcreteProductB2();
- }
- }
-
- // 客户端代码
- public class Client {
- public static void main(String[] args) {
- AbstractFactory factory1 = new ConcreteFactory1();
- ProductA productA1 = factory1.createProductA();
- productA1.useA(); // 输出:Using product A1
- ProductB productB1 = factory1.createProductB();
- productB1.useB(); // 输出:Using product B1
-
- AbstractFactory factory2 = new ConcreteFactory2();
- ProductA productA2 = factory2.createProductA();
- productA2.useA(); // 输出:Using product A2
- ProductB productB2 = factory2.createProductB();
- productB2.useB(); // 输出:Using product B2
- }
- }
明确工厂职责:
- 确保工厂类或方法专注于对象创建,避免承担过多业务逻辑,保持其单一职责。如果工厂过于复杂,可能需要进一步抽象或拆分为多个工厂。
- 对于工厂方法模式和抽象工厂模式,要清晰划分工厂接口与具体工厂类的责任,确保接口的通用性和具体工厂类的可扩展性。
遵守开闭原则:
- 工厂模式的设计应遵循开闭原则,即对扩展开放,对修改关闭。新增产品时,应通过增加新的工厂类(工厂方法模式)或新的具体工厂子类(抽象工厂模式),而不是修改已有工厂类的代码。
- 对于简单工厂模式,虽然直接修改工厂类会导致违反开闭原则,但在简单场景下,或者产品种类较少、不易变动时,仍不失为一种实用的选择。如果预计产品种类会频繁增加或变动,建议使用工厂方法或抽象工厂模式。
处理依赖关系:
- 如果产品类之间存在复杂的依赖关系,或者需要一起创建一组相关对象,应考虑使用抽象工厂模式,它能更好地管理产品族的创建。
- 对于简单工厂或工厂方法模式,如果产品类的依赖关系比较简单,可以直接在工厂中创建或注入依赖。如果依赖关系较复杂,可能需要配合依赖注入框架或服务定位器模式来管理。
控制类的个数:
- 工厂模式可能会增加类的数量,特别是在产品种类较多时。应合理规划类结构,避免类爆炸。可以通过模块化、分包等方式组织代码,提高可读性和可维护性。
- 对于简单工厂模式,如果产品种类过多导致工厂类庞大,可以考虑使用策略模式或枚举类等方式替代部分简单工厂功能。
考虑使用场景:
- 工厂模式并非所有情况下的首选解决方案。对于简单对象的创建,直接使用构造函数或静态工厂方法可能更为简洁。只有在对象创建逻辑复杂、需要动态决定创建何种对象,或者希望将对象创建细节与使用分离时,才应考虑使用工厂模式。
测试与调试:
- 工厂模式可能会增加代码的复杂性,影响测试的便利性。应确保工厂类及其创建的产品类具有良好的可测试性,如提供适当的构造函数、依赖注入点或模拟接口,以便于单元测试。
- 调试时,注意跟踪工厂创建对象的过程,特别是涉及多层工厂或工厂链时,确保对象的创建路径符合预期。
代码复用与扩展:
- 如果多个工厂有相似的创建逻辑,可以考虑提取公共部分到基类或工具类中,避免代码重复。
- 在设计工厂接口时,要考虑未来的扩展性,确保接口定义能够适应潜在的新产品类型。
性能与资源管理:
- 如果工厂模式用于创建资源密集型对象(如数据库连接、文件句柄等),需要考虑资源的有效管理和回收,避免资源泄露。
- 对于工厂方法模式,如果工厂类实例化成本较高,可以考虑使用单例模式或享元模式来优化。
总结来说,使用工厂模式时,应关注职责划分、开闭原则的遵循、依赖关系管理、类数量控制、使用场景选择、测试与调试的便利性、代码复用与扩展性以及性能与资源管理等方面的问题,以确保模式的有效运用和系统的健壮性。