创建型模式 - 工厂模式 (Factory pattern)

创建型模式 - 工厂模式 (Factory pattern)

工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,将对象的创建和使用分离,使得代码更具可维护性和可扩展性。常见的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式


简单工厂
违背开闭原则,简单工厂模式并不属于 GoF 23 种设计模式,但它是思想是工厂模式的基础。

需求描述
在一个图形绘制系统里,需要根据用户输入的形状类型(圆形、矩形、三角形)来创建相应的形状对象并绘制。简单工厂模式可将形状对象的创建逻辑封装在一个工厂类中。

// 抽象形状类
abstract class Shape {
    public abstract void draw();
}

// 圆形类
class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}

// 矩形类
class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}

// 三角形类
class Triangle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制三角形");
    }
}

// 简单工厂类
class ShapeFactory {
    public static Shape createShape(String shapeType) {
        if ("Circle".equalsIgnoreCase(shapeType)) {
            return new Circle();
        } else if ("Rectangle".equalsIgnoreCase(shapeType)) {
            return new Rectangle();
        } else if ("Triangle".equalsIgnoreCase(shapeType)) {
            return new Triangle();
        }
        return null;
    }
}

// 客户端代码
public class SimpleFactoryExample {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.createShape("Circle");
        if (circle != null) {
            circle.draw();
        }

        Shape rectangle = ShapeFactory.createShape("Rectangle");
        if (rectangle != null) {
            rectangle.draw();
        }

        Shape triangle = ShapeFactory.createShape("Triangle");
        if (triangle != null) {
            triangle.draw();
        }
    }
}

工厂方法模式

需求描述
在一个应用程序中,需要记录不同类型的日志,如文件日志、数据库日志。工厂方法模式可让每个具体的日志记录器都有对应的工厂类来创建。

// 抽象日志记录器类
abstract class Logger {
    public abstract void log(String message);
}

// 文件日志记录器类
class FileLogger extends Logger {
    @Override
    public void log(String message) {
        System.out.println("文件日志: " + message);
    }
}

// 数据库日志记录器类
class DatabaseLogger extends Logger {
    @Override
    public void log(String message) {
        System.out.println("数据库日志: " + message);
    }
}

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

// 文件日志记录器工厂类
class FileLoggerFactory extends LoggerFactory {
    @Override
    public Logger createLogger() {
        return new FileLogger();
    }
}

// 数据库日志记录器工厂类
class DatabaseLoggerFactory extends LoggerFactory {
    @Override
    public Logger createLogger() {
        return new DatabaseLogger();
    }
}

// 客户端代码
public class FactoryMethodExample {
    public static void main(String[] args) {
        LoggerFactory fileLoggerFactory = new FileLoggerFactory();
        Logger fileLogger = fileLoggerFactory.createLogger();
        fileLogger.log("这是一条文件日志消息");

        LoggerFactory databaseLoggerFactory = new DatabaseLoggerFactory();
        Logger databaseLogger = databaseLoggerFactory.createLogger();
        databaseLogger.log("这是一条数据库日志消息");
    }
}

抽象工厂模式

需求描述
在一个跨平台的应用程序中,需要根据不同的操作系统(Windows、MacOS)创建不同风格的界面组件(按钮、文本框)。抽象工厂模式可以提供一个创建一系列相关或相互依赖对象的接口。

// 抽象按钮类
interface Button {
    void click();
}

// Windows 按钮类
class WindowsButton implements Button {
    @Override
    public void click() {
        System.out.println("Windows 按钮被点击");
    }
}

// MacOS 按钮类
class MacOSButton implements Button {
    @Override
    public void click() {
        System.out.println("MacOS 按钮被点击");
    }
}

// 抽象文本框类
interface TextBox {
    void inputText(String text);
}

// Windows 文本框类
class WindowsTextBox implements TextBox {
    @Override
    public void inputText(String text) {
        System.out.println("Windows 文本框输入: " + text);
    }
}

// MacOS 文本框类
class MacOSTextBox implements TextBox {
    @Override
    public void inputText(String text) {
        System.out.println("MacOS 文本框输入: " + text);
    }
}

// 抽象工厂类
interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
    // 这里还能横向拓展多个方法
    // Select createSelect();
    // TextArea createTextArea();
    // Input createInput();
}

// Windows 工厂类
class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextBox createTextBox() {
        return new WindowsTextBox();
    }
}

// MacOS 工厂类
class MacOSFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacOSButton();
    }

    @Override
    public TextBox createTextBox() {
        return new MacOSTextBox();
    }
}

// 客户端代码
public class AbstractFactoryExample {
    public static void main(String[] args) {
        GUIFactory windowsFactory = new WindowsFactory();
        Button windowsButton = windowsFactory.createButton();
        TextBox windowsTextBox = windowsFactory.createTextBox();
        windowsButton.click();
        windowsTextBox.inputText("Hello from Windows!");

        GUIFactory macosFactory = new MacOSFactory();
        Button macosButton = macosFactory.createButton();
        TextBox macosTextBox = macosFactory.createTextBox();
        macosButton.click();
        macosTextBox.inputText("Hello from MacOS!");
    }
}

看到这里你可能工厂方法模式和抽象工厂模式觉得它俩很像?好像两种都能实现上面的例子?依旧区别不开???

好,那就再举个例子,让它们代码尽量一样,从中找不同

工厂方法

// 抽象产品
interface Product {
    void use();
}

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

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

// 抽象工厂
abstract class Factory {
    public abstract Product createProduct();
}

// 具体工厂 A,生产产品 A
class ConcreteFactoryA extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂 B,生产产品 B
class ConcreteFactoryB extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 客户端代码
public class FactoryMethodPatternDemo {
    public static void main(String[] args) {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.use();

        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.use();
    }
}

抽象工厂

// 抽象产品 A
interface ProductA {
    void useA();
}

// 具体产品 A1
class ConcreteProductA1 implements ProductA {
    @Override
    public void useA() {
        System.out.println("使用产品 A1");
    }
}

// 具体产品 A2
class ConcreteProductA2 implements ProductA {
    @Override
    public void useA() {
        System.out.println("使用产品 A2");
    }
}

// 抽象产品 B
interface ProductB {
    void useB();
}

// 具体产品 B1
class ConcreteProductB1 implements ProductB {
    @Override
    public void useB() {
        System.out.println("使用产品 B1");
    }
}

// 具体产品 B2
class ConcreteProductB2 implements ProductB {
    @Override
    public void useB() {
        System.out.println("使用产品 B2");
    }
}

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

// 具体工厂 1,生产产品 A1 和产品 B1
class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}

// 具体工厂 2,生产产品 A2 和产品 B2
class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

// 客户端代码
public class AbstractFactoryPatternDemo {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        ProductB productB1 = factory1.createProductB();
        productA1.useA();
        productB1.useB();

        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        ProductB productB2 = factory2.createProductB();
        productA2.useA();
        productB2.useB();
    }
}

看出区别了吗?
工厂方法模式的 Product A 和 B 之间从业务层面看,它俩没什么联系.
抽象工厂模式的 Product A 和 B 就有一种, 系列 1 的 A 产品 和 B 产品, 系列 2 的产品 A 和 B 的产品族的概念.

换个角度来理解上面抽象工厂模式的例子你可能更好的理解.
例如游戏装备中的套装概念
暗黑系套装的头盔(产品A1)和护腿(产品B1)
另一套是光明系的头盔(产品A2)和护腿(产品B2)
这俩者之间就有一个族的概念
如果这时候你出了一个武器(产品C), 这时候你需要再定义一个 ProductC, 然后有暗黑武器(产品C1)和光明武器(产品C2)两个具体产品类去实现 ProductC, 然后在工厂类 AbstractFactory 再去添加方法 createProductC(), 这样同一套创建出来的产品就会是一个套装,以后再增加DEFG…都可以继续扩展

以下是需要新增的代码

// 抽象产品 C - 武器
interface ProductC {
    void useA();
}

// 具体产品 C1 - 暗黑系
class ConcreteProductC1 implements ProductC {
    @Override
    public void useA() {
        System.out.println("使用产品 C1");
    }
}

// 具体产品 C2 - 光明系
class ConcreteProductC2 implements ProductC {
    @Override
    public void useA() {
        System.out.println("使用产品 C2");
    }
}

// 抽象工厂
interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
    // 然后抽象工厂则需要加创建C的方法
    // ProductC createProductC();
}

应用场景

  • 工厂方法模式:适用于当一个类不知道它所需要的对象的类时,或者一个类希望由其子类来指定创建对象的类的情况。例如,在游戏开发中,不同类型的怪物由不同的工厂子类来创建。
  • 抽象工厂模式:适用于需要创建一组相关的产品对象,并且希望确保这些产品对象之间的兼容性的情况。例如,在开发一个跨平台的应用程序时,不同的操作系统需要不同的界面组件(如按钮、文本框等),可以使用抽象工厂模式来创建适合每个操作系统的一组界面组件。

扩展性

  • 工厂方法模式:当需要添加新的产品时,只需要创建一个新的具体产品类和对应的具体工厂类,对原有代码的修改较少,符合开闭原则。
  • 抽象工厂模式:如果要增加一个新的产品族,只需要添加一个新的具体工厂类和对应的具体产品类;但如果要增加一个新的产品类型,需要修改抽象工厂接口及其所有具体工厂实现类,扩展性相对较差。

你可能感兴趣的:(Java设计模式,设计模式,java)