Skip to content

工厂模式

介绍

工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象的最佳方式,使创建对象的过程和业务逻辑解耦。在实际应用场景中,当我们需要根据条件创建不同类型的对象且客户无需知道具体类型信息时,工厂模式就显得尤为有用

Java工厂模式是一种常见的创建型设计模式,旨在封装对象的创建过程,以减少代码之间的耦合度,提高代码的可维护性和可扩展性。工厂模式主要有三种类型:简单工厂模式、工厂方法模式和抽象工厂模式

  1. 简单工厂模式:这种模式涉及一个工厂类,它根据客户端的需求创建不同的产品对象。这种模式通常由三个角色组成:抽象产品类、具体产品类和工厂类。抽象产品类定义产品的共性,具体产品类实现产品接口,工厂类负责创建具体产品的实例
  2. 工厂方法模式:这种模式通过定义一个工厂接口和多个具体的工厂实现类,实现了客户端与具体产品类的解耦。每个具体工厂类只能创建一个具体产品类的实例
  3. 抽象工厂模式:这是一种针对产品族的创建模式,通过定义一个抽象工厂接口和多个具体工厂实现类,实现了客户端与具体产品族的解耦。多个抽象产品类,每个抽象产品类可以派生出多个具体产品类

工厂模式的核心思想是将对象的创建和使用分离,从而降低耦合度,提高代码的可维护性和可扩展性 使用工厂模式可以避免在代码中使用直接的new操作来创建对象,这样可以更容易地进行单元测试和代码重构

为何要使用工厂模式?

假设有一个动物王国,其中包含多种动物,如狗、猫等,每种动物都有各自的叫声行为。如果我们直接创建动物实例,当增加新的动物种类时,代码就会受到影响。

此时,我们可以利用工厂模式,创建一个AnimalFactory来根据不同需求生成不同种类的动物。

java
// 未使用工厂模式前的问题示例
Dog dog = new Dog();
dog.bark();

Cat cat = new Cat();
cat.meow();

简单工厂模式

简单工厂模式是一种创建型设计模式,它提供一个专门的类来负责创建其他类的实例,而无需在客户端代码中直接使用new关键字。 这种模式的优点在于降低了客户端与具体产品类之间的耦合度,使得客户端无需关心具体产品的创建细节

简单工厂模式的核心在于一个工厂类,这个工厂类根据传入的参数或其他条件,返回对应的产品类实例。 客户端只需要与工厂类交互,而无需知道具体产品类的实现细节

代码案例:

java
// 产品接口  
public interface Car {  
    void drive();  
}  
  
// 具体产品类A  
public class SportsCar implements Car {  
    @Override  
    public void drive() {  
        System.out.println("Driving a sports car!");  
    }  
}  
  
// 具体产品类B  
public class SuvCar implements Car {  
    @Override  
    public void drive() {  
        System.out.println("Driving an SUV!");  
    }  
}  
  
// 简单工厂类  
public class CarFactory {  
    public static Car createCar(String type) {  
        if ("sports".equalsIgnoreCase(type)) {  
            return new SportsCar();  
        } else if ("suv".equalsIgnoreCase(type)) {  
            return new SuvCar();  
        } else {  
            throw new IllegalArgumentException("Invalid car type: " + type);  
        }  
    }  
}  
  
// 客户端代码  
public class Client {  
    public static void main(String[] args) {  
        Car sportsCar = CarFactory.createCar("sports");  
        sportsCar.drive();  
          
        Car suvCar = CarFactory.createCar("suv");  
        suvCar.drive();  
    }  
}

工厂方法模式

工厂方法模式是对简单工厂模式的进一步抽象化,它定义一个用于创建对象的接口,让子类决定实例化哪一个类。 工厂方法模式使得一个类的实例化延迟到其子类。

工厂方法模式的核心在于定义一个创建产品的抽象工厂接口,具体的工厂子类实现这个接口并返回对应的具体产品实例。 这样,客户端代码只需要与抽象工厂接口交互,而无需关心具体工厂和产品类的实现细节。

代码案例:

java
// 产品接口  
public interface Car {  
    void drive();  
}  
  
// 具体产品类A  
public class SportsCar implements Car {  
    @Override  
    public void drive() {  
        System.out.println("Driving a sports car!");  
    }  
}  
  
// 具体产品类B  
public class SuvCar implements Car {  
    @Override  
    public void drive() {  
        System.out.println("Driving an SUV!");  
    }  
}  
  
// 抽象工厂接口  
public interface CarFactory {  
    Car createCar();  
}  
  
// 具体工厂类A  
public class SportsCarFactory implements CarFactory {  
    @Override  
    public Car createCar() {  
        return new SportsCar();  
    }  
}  
  
// 具体工厂类B  
public class SuvCarFactory implements CarFactory {  
    @Override  
    public Car createCar() {  
        return new SuvCar();  
    }  
}  
  
// 客户端代码  
public class Client {  
    public static void main(String[] args) {  
        CarFactory sportsCarFactory = new SportsCarFactory();  
        Car sportsCar = sportsCarFactory.createCar();  
        sportsCar.drive();  
          
        CarFactory suvCarFactory = new SuvCarFactory();  
        Car suvCar = suvCarFactory.createCar();  
        suvCar.drive();  
    }  
}

抽象工厂模式

简介

抽象工厂模式(Abstract Factory Pattern)是工厂模式的一种扩展形式,它提供了一种方式来封装一组具有共同主题的单个工厂,而不需要指定它们的具体类。 这种模式的主要目的是创建一个系统的框架,而不指定具体类,以便将客户端与具体产品的实现解耦,增加系统的灵活性和可扩展性。

在抽象工厂模式中,抽象工厂类负责定义创建产品对象的接口,而具体工厂类则负责生成具体的产品对象。这些产品对象通常属于一个产品族,即一组相互关联或依赖的产品。 抽象工厂模式允许客户端在不指定具体产品的情况下,通过抽象工厂类获取一系列相关的产品对象。

场景

抽象工厂模式通常适用于以下场景:

  1. 当系统需要创建一系列相互关联或依赖的对象时,可以使用抽象工厂模式来简化对象的创建过程
  2. 当客户端需要一组相关的产品对象,而不需要关心其具体实现时,抽象工厂模式能够提供一种灵活的方式来获取这些对象
  3. 当系统中存在多个产品族,且每个产品族中的产品具有相似的接口时,可以使用抽象工厂模式来统一管理这些产品族的创建

代码案例:

java
// 抽象产品接口 - 汽车  
public interface Car {  
    void start();  
    void stop();  
}  
  
// 具体产品类 - 运动型汽车  
public class SportsCar implements Car {  
    @Override  
    public void start() {  
        System.out.println("Starting sports car!");  
    }  
  
    @Override  
    public void stop() {  
        System.out.println("Stopping sports car!");  
    }  
}  
  
// 具体产品类 - SUV型汽车  
public class SuvCar implements Car {  
    @Override  
    public void start() {  
        System.out.println("Starting SUV car!");  
    }  
  
    @Override  
    public void stop() {  
        System.out.println("Stopping SUV car!");  
    }  
}

接下来,我们定义抽象工厂接口和具体工厂类:

java
// 抽象工厂接口  
public interface CarFactory {  
    Car createCar();  
}  
  
// 具体工厂类 - 运动型汽车工厂  
public class SportsCarFactory implements CarFactory {  
    @Override  
    public Car createCar() {  
        return new SportsCar();  
    }  
}  
  
// 具体工厂类 - SUV型汽车工厂  
public class SuvCarFactory implements CarFactory {  
    @Override  
    public Car createCar() {  
        return new SuvCar();  
    }  
}

最后,我们编写客户端代码来使用抽象工厂模式:

java
public class Client {  
    public static void main(String[] args) {  
        // 使用运动型汽车工厂创建运动型汽车  
        CarFactory sportsCarFactory = new SportsCarFactory();  
        Car sportsCar = sportsCarFactory.createCar();  
        sportsCar.start();  
        sportsCar.stop();  
  
        // 使用SUV型汽车工厂创建SUV型汽车  
        CarFactory suvCarFactory = new SuvCarFactory();  
        Car suvCar = suvCarFactory.createCar();  
        suvCar.start();  
        suvCar.stop();  
    }  
}

在这个例子中,CarFactory 是一个抽象工厂接口,它定义了创建汽车对象的方法。SportsCarFactory 和 SuvCarFactory 是实现了这个接口的具体工厂类,分别用于创建运动型汽车和SUV型汽车的具体实例。 客户端代码通过抽象工厂接口与具体工厂类交互,从而可以创建不同类型的汽车对象,而无需关心具体产品的实现细节。

抽象工厂模式使得系统更加灵活和可扩展,因为可以通过添加新的具体工厂类来引入新的产品族,而无需修改现有的客户端代码。 同时,它也降低了客户端与具体产品之间的耦合度,提高了系统的可维护性。 然而,抽象工厂模式也增加了系统的复杂性,因为需要引入更多的接口和类。 因此,在使用抽象工厂模式时需要根据具体需求进行权衡和选择。

优缺点

优点:

  1. 解耦:工厂模式实现了创建者与调用者的解耦。调用者无需关心创建对象的具体过程,只需调用工厂方法即可获取所需对象。这降低了代码的耦合度,提高了系统的灵活性和可扩展性。
  2. 封装性:工厂模式将对象的创建过程封装在工厂类中,隐藏了对象的创建细节。这有助于隐藏复杂逻辑,使代码更加清晰易懂。
  3. 单一职责原则:工厂模式使得每个具体工厂类只负责创建一类对象,符合单一职责原则。这有助于降低代码的复杂度,提高系统的可维护性。
  4. 易于扩展:当需要添加新的产品类时,只需添加相应的具体产品类和工厂类,而无需修改已有的代码。这降低了修改代码的风险和成本,使得系统更易于扩展。
  5. 提高性能:工厂模式可以预先创建并缓存一些对象,避免在需要时频繁创建对象,从而提高系统的性能。

缺点:

  1. 增加系统复杂度:引入工厂模式意味着需要创建额外的工厂类,这可能会增加系统的复杂度。在简单的应用场景下,过度使用工厂模式可能导致代码冗余和难以维护。
  2. 增加了代码抽象度:工厂模式的实现涉及更多的抽象层,这可能导致代码更加难以理解。对于初学者或不熟悉工厂模式的开发者来说,可能需要花费更多时间来理解和学习。
  3. 违背开闭原则:虽然工厂方法模式符合开闭原则(对扩展开放,对修改封闭),但简单工厂模式却在一定程度上违背了这一原则。因为当需要添加新产品时,可能需要修改工厂类的代码,这增加了修改已有代码的风险。
  4. 可能导致过度设计:在某些情况下,过度使用工厂模式可能导致过度设计。如果系统中的对象创建并不复杂或不需要频繁地更换具体实现,那么引入工厂模式可能并不必要,反而增加了系统的复杂性和维护成本。

综上所述,工厂模式在解耦、封装性、单一职责原则和易于扩展等方面具有显著优点,但在增加系统复杂度、代码抽象度、违背开闭原则和可能导致过度设计等方面也存在一些缺点。 因此,在选择是否使用工厂模式时,需要根据具体的业务需求和系统复杂度进行权衡。

总结

总结起来,Java工厂模式是一种常见的设计模式,通过合理地运用,可以在代码设计中实现更好的解耦和扩展性,让程序更加灵活、易于维护。

无论是简单工厂模式还是工厂方法模式,都是在解决创建对象的过程中遇到的问题,选择哪种模式取决于具体的应用场景和需求。