MST
星途 面试题库

面试题:Java中工厂方法模式与抽象工厂模式的区别

请阐述在Java中工厂方法模式与抽象工厂模式的主要区别,并分别举例说明它们在实际项目中的应用场景。
31.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

主要区别

  1. 定义与意图
    • 工厂方法模式:定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
    • 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  2. 结构复杂度
    • 工厂方法模式:结构相对简单,只有一个抽象产品类和一个具体产品类层次结构,工厂类有一个抽象创建方法,具体工厂类实现该方法创建具体产品。
    • 抽象工厂模式:结构更复杂,有多个抽象产品类和具体产品类层次结构,抽象工厂类有多个创建不同类型产品的抽象方法,具体工厂类实现这些方法创建一系列相关产品。
  3. 灵活性与可维护性
    • 工厂方法模式:当需要新增一种产品时,只需新增一个具体产品类和一个对应的具体工厂类,符合开闭原则,灵活性较好,维护相对容易。
    • 抽象工厂模式:当需要新增一种产品时,需要修改抽象工厂接口及所有具体工厂类,违反开闭原则,灵活性和维护性较差,但对于创建一组相关产品非常方便。
  4. 创建对象的粒度
    • 工厂方法模式:每次创建一个具体产品对象。
    • 抽象工厂模式:每次创建一系列相关的产品对象。

应用场景举例

  1. 工厂方法模式应用场景
    • 日志记录系统:不同的日志记录方式如文件日志、数据库日志等。定义一个抽象的日志记录工厂类,有一个抽象的创建日志记录器方法。具体的文件日志工厂类实现该方法创建文件日志记录器,数据库日志工厂类实现该方法创建数据库日志记录器。
    • 代码示例
// 抽象产品类
abstract class Logger {
    public abstract void log(String message);
}

// 具体产品类1
class FileLogger extends Logger {
    @Override
    public void log(String message) {
        System.out.println("Logging to file: " + message);
    }
}

// 具体产品类2
class DatabaseLogger extends Logger {
    @Override
    public void log(String message) {
        System.out.println("Logging to database: " + message);
    }
}

// 抽象工厂类
abstract class LoggerFactory {
    public abstract Logger createLogger();
}

// 具体工厂类1
class FileLoggerFactory extends LoggerFactory {
    @Override
    public Logger createLogger() {
        return new FileLogger();
    }
}

// 具体工厂类2
class DatabaseLoggerFactory extends LoggerFactory {
    @Override
    public Logger createLogger() {
        return new DatabaseLogger();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        LoggerFactory fileLoggerFactory = new FileLoggerFactory();
        Logger fileLogger = fileLoggerFactory.createLogger();
        fileLogger.log("This is a file log message");

        LoggerFactory databaseLoggerFactory = new DatabaseLoggerFactory();
        Logger databaseLogger = databaseLoggerFactory.createLogger();
        databaseLogger.log("This is a database log message");
    }
}
  1. 抽象工厂模式应用场景
    • 跨平台UI组件创建:在不同的操作系统(如Windows、MacOS)上创建不同风格的UI组件,如按钮、文本框等。定义一个抽象工厂类,有创建按钮和文本框的抽象方法。具体的Windows工厂类实现这些方法创建Windows风格的按钮和文本框,MacOS工厂类实现这些方法创建MacOS风格的按钮和文本框。
    • 代码示例
// 抽象产品类1:按钮
abstract class Button {
    public abstract void render();
}

// 具体产品类1.1:Windows按钮
class WindowsButton extends Button {
    @Override
    public void render() {
        System.out.println("Rendering a Windows button");
    }
}

// 具体产品类1.2:MacOS按钮
class MacOSButton extends Button {
    @Override
    public void render() {
        System.out.println("Rendering a MacOS button");
    }
}

// 抽象产品类2:文本框
abstract class TextField {
    public abstract void render();
}

// 具体产品类2.1:Windows文本框
class WindowsTextField extends TextField {
    @Override
    public void render() {
        System.out.println("Rendering a Windows text field");
    }
}

// 具体产品类2.2:MacOS文本框
class MacOSTextField extends TextField {
    @Override
    public void render() {
        System.out.println("Rendering a MacOS text field");
    }
}

// 抽象工厂类
abstract class GUIFactory {
    public abstract Button createButton();
    public abstract TextField createTextField();
}

// 具体工厂类1:Windows工厂
class WindowsGUIFactory extends GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextField createTextField() {
        return new WindowsTextField();
    }
}

// 具体工厂类2:MacOS工厂
class MacOSGUIFactory extends GUIFactory {
    @Override
    public Button createButton() {
        return new MacOSButton();
    }

    @Override
    public TextField createTextField() {
        return new MacOSTextField();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        GUIFactory windowsFactory = new WindowsGUIFactory();
        Button windowsButton = windowsFactory.createButton();
        TextField windowsTextField = windowsFactory.createTextField();
        windowsButton.render();
        windowsTextField.render();

        GUIFactory macOSFactory = new MacOSGUIFactory();
        Button macOSButton = macOSFactory.createButton();
        TextField macOSTextField = macOSFactory.createTextField();
        macOSButton.render();
        macOSTextField.render();
    }
}