背景/问题

  • 在某些情况下,需要创建一系列相关或相互依赖的对象,这些对象属于一组相关的产品族。
  • 同时,系统需要保证这些产品族之间的一致性。
  • 如果直接在代码中创建这些对象,会使得代码与具体产品的细节紧密耦合,不利于后续的扩展和维护。

解决方案:

  • 抽象工厂模式提供了一个接口,用于创建一系列相关或相互依赖的对象。
  • 通过使用抽象工厂接口及其具体实现,可以将对象的创建与客户端代码分离,从而实现系统的松耦合。

抽象工厂模式

用于生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

解析

生活场景模拟

工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)

上一章的案例图解

【Java设计模式】创建型——抽象工厂模式-LMLPHP

意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

主要解决

主要解决接口选择的问题。

何时使用

系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

如何解决

在一个产品族里面,定义多个产品。

关键代码

在一个工厂里聚合多个同类产品。

抽象工厂模式涉及多个角色:

抽象工厂(Abstract Factory):声明了一组用于创建不同产品的抽象方法。具体的工厂类必须实现这些方法来创建具体的产品对象。
具体工厂(Concrete Factory):实现抽象工厂接口,负责创建特定种类的产品对象。
抽象产品(Abstract Product):定义了产品的通用接口,具体产品必须实现这个接口。
具体产品(Concrete Product):实现抽象产品接口,是抽象工厂创建的实际对象。

代码示例

// 抽象产品接口:操作系统
interface OperatingSystem {
    void run();
}

// 具体产品:Windows操作系统
class WindowsOS implements OperatingSystem {
    @Override
    public void run() {
        System.out.println("Running Windows OS");
    }
}

// 具体产品:Linux操作系统
class LinuxOS implements OperatingSystem {
    @Override
    public void run() {
        System.out.println("Running Linux OS");
    }
}

// 抽象产品接口:应用程序
interface Application {
    void open();
}

// 具体产品:Word应用程序
class WordApplication implements Application {
    @Override
    public void open() {
        System.out.println("Opening Word Application");
    }
}

// 具体产品:Excel应用程序
class ExcelApplication implements Application {
    @Override
    public void open() {
        System.out.println("Opening Excel Application");
    }
}

// 抽象工厂接口
interface SoftwareFactory {
    OperatingSystem createOperatingSystem();
    Application createApplication();
}

// 具体工厂:Windows工厂
class WindowsFactory implements SoftwareFactory {
    @Override
    public OperatingSystem createOperatingSystem() {
        return new WindowsOS();
    }

    @Override
    public Application createApplication() {
        return new ExcelApplication();
    }
}

// 具体工厂:Linux工厂
class LinuxFactory implements SoftwareFactory {
    @Override
    public OperatingSystem createOperatingSystem() {
        return new LinuxOS();
    }

    @Override
    public Application createApplication() {
        return new WordApplication();
    }
}

// 在这个示例中,抽象工厂模式通过SoftwareFactory接口和其实现类来创建不同类型的操作系统和应用程序。
// 客户端代码可以根据需要选择不同的工厂实例来创建不同的产品组合。
public class Client {
    public static void main(String[] args) {
        SoftwareFactory windowsFactory = new WindowsFactory();
        OperatingSystem windowsOS = windowsFactory.createOperatingSystem();
        Application windowsApp = windowsFactory.createApplication();

        windowsOS.run();
        windowsApp.open();

        SoftwareFactory linuxFactory = new LinuxFactory();
        OperatingSystem linuxOS = linuxFactory.createOperatingSystem();
        Application linuxApp = linuxFactory.createApplication();

        linuxOS.run();
        linuxApp.open();
    }
}

优点

抽象工厂模式的使用可以带来以下效果:

  1. 产品族一致性:抽象工厂确保创建的产品是一组相关的产品族,保证了这些产品之间的一致性。
  2. 松耦合:客户端代码不需要直接依赖于具体产品,只需要通过抽象工厂接口创建产品,从而降低了代码的耦合度。
  3. 可扩展性:增加新的产品族或产品变得相对容易,只需要添加新的具体工厂和产品类即可,不需要修改现有代码。

缺点

抽象工厂模式要求系统中的每个产品族都必须有一个对应的具体工厂,这可能增加了系统的复杂性。

抽象工厂模式适用于需要创建一系列相关产品并保证它们之间一致性的情况,例如图形界面库中的UI元素,不同操作系统下的界面组件等。通过使用抽象工厂模式,可以更好地管理和组织这些产品的创建过程。

应用场景

  1. JDK中Calendar的getInstance方法
  2. JDBC中Connection对象的获取
  3. Hibernate中SessionFactory创建Session
  4. spring中IOC容器创建管理bean对象
  5. XML解析时的DocumentBuilderFactory创建解析器对象
  6. 反射中Class对象的newInstance()
04-07 11:14