Java设计模式之工厂模式

1. 引言

工厂模式(Factory Pattern)是创建型设计模式之一,旨在提供一个创建对象的接口,而不是直接通过 new 关键字来实例化对象。工厂模式在提高代码的可维护性、可扩展性和灵活性方面具有显著优势。

更多设计模式请参考:Java 中的 23 种设计模式详解

2. 工厂模式的分类

工厂模式主要分为三类:

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

2.1 简单工厂模式

概念

简单工厂模式通过一个静态方法,根据传入的参数,返回不同类型的对象。尽管这种模式在严格意义上不被认为是一种设计模式,但它是其他工厂模式的基础。

优点

  • 客户端不需要知道具体产品类的类名,只需要知道一个参数即可创建产品实例,降低了客户端与具体产品类的耦合。

缺点

  • 增加新的产品时需要修改工厂类,违反了开放-关闭原则(OCP)。
  • 简单工厂模式中的工厂类集中了所有产品的创建逻辑,职责过重,不利于代码维护。
使用场景
  • 当工厂类负责创建的对象比较少时。
  • 客户端只需知道传入工厂类的参数即可创建对象时。
实现示例

假设我们有一个产品接口和几种具体产品:

// 产品接口
public interface Product {
    void use();
}

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

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

现在我们创建一个简单工厂类:

public class SimpleFactory {
    // 静态方法,根据传入的参数创建不同的产品对象
    public static Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ProductA();
            case "B":
                return new ProductB();
            default:
                throw new IllegalArgumentException("Unknown product type");
        }
    }
}

使用示例:

public class Main {
    public static void main(String[] args) {
        // 创建产品A
        Product productA = SimpleFactory.createProduct("A");
        productA.use();

        // 创建产品B
        Product productB = SimpleFactory.createProduct("B");
        productB.use();
    }
}

2.2 工厂方法模式

概念

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

优点

  • 遵循开放-关闭原则,新增产品时只需增加相应的具体产品类和具体工厂类。
  • 遵循单一职责原则,每个具体工厂类只负责创建对应的产品。

缺点

  • 增加了系统的复杂性,增加了类的数量。
使用场景
  • 一个类不知道它所需要的对象的类时。
  • 一个类通过其子类来指定创建哪个对象时。
  • 将创建对象的职责委托给多个工厂子类中的某一个,客户端在使用时通过具体工厂类来创建对象。
实现示例
// 工厂接口
public interface Factory {
    Product createProduct();
}

// 具体工厂A
public class FactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

// 具体工厂B
public class FactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

使用示例:

public class Main {
    public static void main(String[] args) {
        // 创建具体工厂A
        Factory factoryA = new FactoryA();
        // 通过工厂A创建产品A
        Product productA = factoryA.createProduct();
        productA.use();

        // 创建具体工厂B
        Factory factoryB = new FactoryB();
        // 通过工厂B创建产品B
        Product productB = factoryB.createProduct();
        productB.use();
    }
}

2.3 抽象工厂模式

概念

抽象工厂模式提供一个创建一系列相关或依赖对象的接口,而无需指定它们的具体类。抽象工厂模式使得系统能够独立于这些对象的创建过程。

优点

  • 分离了具体类的生成,符合开放-关闭原则。
  • 可以在不修改已有代码的情况下增加新的产品系列。
  • 通过一个工厂创建多个相关的产品对象,保证产品对象的一致性。

缺点

  • 增加了系统的复杂性,增加了类的数量。
使用场景
  • 一个系统需要独立于其产品创建、组合和表示时。
  • 一个系统需要配置多个产品系列中的一个时。
  • 需要强调一系列相关的产品对象一起使用时。
实现示例

假设我们有两个系列的产品,A系列和B系列,每个系列都有产品1和产品2:

// 抽象产品1
public interface Product1 {
    void use();
}

// 抽象产品2
public interface Product2 {
    void use();
}

// 具体产品A1
public class ProductA1 implements Product1 {
    @Override
    public void use() {
        System.out.println("Using Product A1");
    }
}

// 具体产品A2
public class ProductA2 implements Product2 {
    @Override
    public void use() {
        System.out.println("Using Product A2");
    }
}

// 具体产品B1
public class ProductB1 implements Product1 {
    @Override
    public void use() {
        System.out.println("Using Product B1");
    }
}

// 具体产品B2
public class ProductB2 implements Product2 {
    @Override
    public void use() {
        System.out.println("Using Product B2");
    }
}

现在我们创建抽象工厂接口及其具体工厂:

// 抽象工厂
public interface AbstractFactory {
    Product1 createProduct1();
    Product2 createProduct2();
}

// 具体工厂A
public class FactoryA implements AbstractFactory {
    @Override
    public Product1 createProduct1() {
        return new ProductA1();
    }

    @Override
    public Product2 createProduct2() {
        return new ProductA2();
    }
}

// 具体工厂B
public class FactoryB implements AbstractFactory {
    @Override
    public Product1 createProduct1() {
        return new ProductB1();
    }

    @Override
    public Product2 createProduct2() {
        return new ProductB2();
    }
}

使用示例:

public class Main {
    public static void main(String[] args) {
        // 创建具体工厂A
        AbstractFactory factoryA = new FactoryA();
        // 通过工厂A创建产品A1和A2
        Product1 productA1 = factoryA.createProduct1();
        Product2 productA2 = factoryA.createProduct2();
        productA1.use();
        productA2.use();

        // 创建具体工厂B
        AbstractFactory factoryB = new FactoryB();
        // 通过工厂B创建产品B1和B2
        Product1 productB1 = factoryB.createProduct1();
        Product2 productB2 = factoryB.createProduct2();
        productB1.use();
        productB2.use();
    }
}

3. 总结

工厂模式是非常有用的设计模式,通过将对象的创建过程封装起来,提供了一种灵活且可扩展的解决方案。在实际开发中,根据具体的需求选择合适的工厂模式,可以显著提高代码的维护性和可扩展性。

简单工厂模式

  • 适用场景: 对象类型较少时。
  • 优点: 客户端只需知道传入参数即可创建对象。
  • 缺点: 新增产品需要修改工厂类,违反开放-关闭原则。

工厂方法模式

  • 适用场景: 对象类型较多且需要频繁扩展时。
  • 优点: 遵循开放-关闭原则和单一职责原则。
  • 缺点: 增加了系统的复杂性和类的数量。

抽象工厂模式

  • 适用场景: 需要创建一系列相关或依赖对象时。
  • 优点: 分离了具体类的生成,保证产品对象的一致性。
  • 缺点: 增加了系统的复杂性和类的数量。

理解并熟练应用工厂模式,是成为优秀Java开发者的重要一环。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐