设计模式系列:工厂模式详解

设计模式是软件开发中的一种经典解决方案,它为我们提供了通用的解决方案来处理常见的设计问题。今天,我们将深入探讨工厂模式(Factory Pattern)及其几种常见的变体:简单工厂模式工厂方法模式抽象工厂模式

一、什么是工厂模式?

工厂模式属于创建型模式,它的核心思想是通过提供一个创建对象的接口,让子类决定实例化哪一个类。工厂模式通过隐藏对象创建的具体细节,提高了代码的可扩展性和灵活性。

工厂模式的主要优势是:

  • 解耦:客户端不需要知道具体的类名,只需要通过工厂来获取对象。

  • 提高可扩展性:可以通过扩展工厂类来支持更多的产品类型,而不需要修改客户端代码。

工厂模式的分类

  1. 简单工厂模式(Simple Factory Pattern)

  2. 工厂方法模式(Factory Method Pattern)

  3. 抽象工厂模式(Abstract Factory Pattern)

二、简单工厂模式(Simple Factory Pattern)

简单工厂模式是最简单的一种工厂模式,它通过一个工厂类来决定实例化哪一种产品类。客户端通过调用工厂类的方法来获取产品对象,而不需要直接创建产品对象。

代码示例:简单工厂模式

首先,我们定义一个简单的产品接口和几个具体的产品类。

// 产品接口
public interface Product {
    void doSomething();
}
​
// 具体产品A
public class ProductA implements Product {
    @Override
    public void doSomething() {
        System.out.println("产品A正在做事情!");
    }
}
​
// 具体产品B
public class ProductB implements Product {
    @Override
    public void doSomething() {
        System.out.println("产品B正在做事情!");
    }
}

接下来,定义一个简单工厂类,根据客户端的需求返回不同的产品对象。

// 简单工厂类
public class ProductFactory {
    public static Product createProduct(String type) {
        if ("A".equalsIgnoreCase(type)) {
            return new ProductA();
        } else if ("B".equalsIgnoreCase(type)) {
            return new ProductB();
        }
        return null;
    }
}

客户端代码通过工厂来创建产品:

public class Client {
    public static void main(String[] args) {
        Product productA = ProductFactory.createProduct("A");
        productA.doSomething();
​
        Product productB = ProductFactory.createProduct("B");
        productB.doSomething();
    }
}

总结

简单工厂模式通过一个工厂类集中处理对象创建,客户端无需直接接触具体的类。缺点是当产品种类较多时,工厂类会变得非常庞大,难以维护。

三、工厂方法模式(Factory Method Pattern)

工厂方法模式解决了简单工厂模式的一个缺点:当产品种类很多时,工厂类变得难以维护。在工厂方法模式中,工厂类不再直接创建产品对象,而是通过继承的方式,让子类决定创建哪一种产品。

代码示例:工厂方法模式

首先,定义一个产品接口和具体产品类(与简单工厂模式相同)。

// 产品接口
public interface Product {
    void doSomething();
}
​
// 具体产品A
public class ProductA implements Product {
    @Override
    public void doSomething() {
        System.out.println("产品A正在做事情!");
    }
}
​
// 具体产品B
public class ProductB implements Product {
    @Override
    public void doSomething() {
        System.out.println("产品B正在做事情!");
    }
}

接下来,定义一个抽象工厂类,并在其子类中实现具体的工厂方法。

// 抽象工厂类
public abstract class ProductFactory {
    public abstract Product createProduct();
}
​
// 具体工厂A
public class ProductAFactory extends ProductFactory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}
​
// 具体工厂B
public class ProductBFactory extends ProductFactory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

客户端代码通过工厂方法来创建产品:

public class Client {
    public static void main(String[] args) {
        ProductFactory factoryA = new ProductAFactory();
        Product productA = factoryA.createProduct();
        productA.doSomething();
​
        ProductFactory factoryB = new ProductBFactory();
        Product productB = factoryB.createProduct();
        productB.doSomething();
    }
}

总结

工厂方法模式通过子类化的方式,将对象创建的责任交给了具体的工厂。每个具体工厂类负责实例化一个产品对象,客户端只需要调用工厂的工厂方法即可获取产品对象。

四、抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式进一步抽象化了工厂方法模式,它提供了一个接口,用于创建一系列相关的或相互依赖的产品,而不需要指定具体的产品类。每个具体的工厂类负责创建一系列相关的产品对象。

代码示例:抽象工厂模式

首先,定义一个产品系列的接口。

// 产品接口1
public interface ProductA {
    void doSomethingA();
}
​
// 产品接口2
public interface ProductB {
    void doSomethingB();
}

然后,定义具体的产品类。

// 具体产品A1
public class ProductA1 implements ProductA {
    @Override
    public void doSomethingA() {
        System.out.println("产品A1正在做事情!");
    }
}
​
// 具体产品A2
public class ProductA2 implements ProductA {
    @Override
    public void doSomethingA() {
        System.out.println("产品A2正在做事情!");
    }
}
​
// 具体产品B1
public class ProductB1 implements ProductB {
    @Override
    public void doSomethingB() {
        System.out.println("产品B1正在做事情!");
    }
}
​
// 具体产品B2
public class ProductB2 implements ProductB {
    @Override
    public void doSomethingB() {
        System.out.println("产品B2正在做事情!");
    }
}

接下来,定义一个抽象工厂类。

// 抽象工厂类
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

定义具体的工厂类。

// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ProductA1();
    }
​
    @Override
    public ProductB createProductB() {
        return new ProductB1();
    }
}
​
// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ProductA2();
    }
​
    @Override
    public ProductB createProductB() {
        return new ProductB2();
    }
}

客户端代码:

public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        productA1.doSomethingA();
        ProductB productB1 = factory1.createProductB();
        productB1.doSomethingB();
​
        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        productA2.doSomethingA();
        ProductB productB2 = factory2.createProductB();
        productB2.doSomethingB();
    }
}

总结

抽象工厂模式可以创建一系列相关的产品,且每个具体工厂都负责生产一组相关产品。它使得客户端可以灵活选择不同的产品系列,而不需要了解具体的产品实现。

五、工厂模式在Spring中的应用

在Spring框架中,工厂模式得到了广泛应用。比如,在Spring的BeanFactoryApplicationContext中,Spring本身充当了一个工厂角色,通过工厂方法来创建Bean对象。而Spring的依赖注入(DI)模式可以看作是工厂模式的一种应用。

Spring工厂示例:简单工厂模式

假设我们有一个接口和两个实现类:

public interface Car {
    void drive();
}
​
public class SedanCar implements Car {
    @Override
    public void drive() {
        System.out.println("驾驶轿车");
    }
}
​
public class SuvCar implements Car {
    @Override
    public void drive() {
        System.out.println("驾驶SUV");
    }
}

然后,我们创建一个工厂类来根据不同的条件返回不同的产品:

import org.springframework.stereotype.Component;
​
@Component
public class CarFactory {
​
    public Car getCar(String type) {
        if ("sedan".equalsIgnoreCase(type)) {
            return new SedanCar();
        } else if ("suv".equalsIgnoreCase(type)) {
            return new SuvCar();
        }
        return null;
    }
}
​

最后,在Spring的应用中,我们可以通过自动注入工厂来获取产品对象。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
@Service
public class CarService {
​
    private final CarFactory carFactory;
​
    @Autowired
    public CarService(CarFactory carFactory) {
        this.carFactory = carFactory;
    }
​
    public void testCarFactory() {
        Car sedan = carFactory.getCar("sedan");
        sedan.drive();
    }
}

总结

在Spring框架中,工厂模式帮助我们更灵活地创建和管理Bean对象,实现了松耦合和易于扩展的设计。

六、结语

通过本文的讲解,我们深入了解了工厂模式的三种常见实现:简单工厂模式、工厂方法模式和抽象工厂模式。每种模式都有其适用的场景,根据需求的不同,可以灵活选择最合适的工厂模式来优化代码设计。

在开发过程中,目前我遇到很少直接使用单独一个工厂模式来解决代码结构上的问题,一般来说都是结合其他几种设计模式一起解决问题,我个人觉得使用设计模式更多的是学习设计思路,而不是生搬硬套,只有多种设计模式相互结合才会写出更好的代码,如果硬套不过是另一种形式的屎山。