简单工厂、工厂方法模式、抽象工厂模式

简介

  • 简单工厂:适合单一产品、创建逻辑简单的场景,但不符合开闭原则。
  • 工厂方法:适合需要扩展多种具体产品的场景,符合开闭原则。
  • 抽象工厂:适合需要创建一组相关对象的场景,支持切换整个产品簇。

简单工厂模式

通过一个工厂类集中处理对象的创建逻辑,根据传入的参数决定创建哪一种产品类的实例。

java 复制代码
// 抽象产品
interface Product {
    void use();
}

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

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

// 简单工厂
class SimpleFactory {
    public Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// 客户端调用
public class Client {
    public static void main(String[] args) {
        SimpleFactory factory = new SimpleFactory();
        Product product = factory.createProduct("A");
        product.use(); // 输出: Using Product A
    }
}

工厂方法模式

定义了一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

核心结构:

  • Product(抽象产品):定义产品的公共接口。
  • ConcreteProduct(具体产品):实现 Product 接口的具体类。
  • Factory(抽象工厂):声明一个工厂方法,用于创建 Product 对象。
  • ConcreteFactory(具体工厂):实现工厂方法,返回一个具体的 ConcreteProduct 实例。
java 复制代码
// 抽象产品
interface Product {
    void use();
}

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

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

// 抽象工厂
abstract class Factory {
    // 工厂方法
    abstract Product createProduct();

    // 使用产品的方法
    void doSomething() {
        Product product = createProduct();
        product.use();
    }
}

// 具体工厂A
class FactoryA extends Factory {
    @Override
    Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂B
class FactoryB extends Factory {
    @Override
    Product createProduct() {
        return new ConcreteProductB();
    }
}

// 客户端调用
public class Client {
    public static void main(String[] args) {
        Factory factoryA = new FactoryA();
        factoryA.doSomething(); // 输出: Using Product A

        Factory factoryB = new FactoryB();
        factoryB.doSomething(); // 输出: Using Product B
    }
}

抽象工厂模式

提供一个接口,用于创建一组相关或依赖对象的家族,而无需指定具体类。 这在需要为不同的"产品族"提供统一的创建方式时非常有用,比如: 不同操作系统下的 UI 控件(按钮、文本框等); 不同风格的主题(深色、浅色); 多平台客户端(PC、移动端)所需的一整套组件。

接口和抽象类都可以实现抽象工厂模式, 但更倾向于使用 接口(interface) 来实现抽象工厂,因为: 更符合面向接口编程的思想; 支持多继承; 可以配合默认方法提供更灵活的设计。

下面是一个完整的 抽象工厂模式(Abstract Factory Pattern) 的 Java 示例实现,涵盖了:

  • 抽象工厂接口
  • 具体工厂类
  • 抽象产品接口
  • 具体产品类
  • 客户端调用

这个例子以"不同风格的 UI 控件"为例:比如 Windows 风格和 Mac 风格的按钮和文本框。


1. 定义抽象产品接口

Button.java - 按钮接口

java 复制代码
public interface Button {
    void render();
}

TextBox.java - 文本框接口

java 复制代码
public interface TextBox {
    void render();
}

2. 实现具体产品类

WindowsButton.java

java 复制代码
class WindowsButton implements Button {
    public void render() {
        System.out.println("Render a Windows style button.");
    }
}

MacButton.java

java 复制代码
class MacButton implements Button {
    public void render() {
        System.out.println("Render a Mac style button.");
    }
}

WindowsTextBox.java

java 复制代码
class WindowsTextBox implements TextBox {
    public void render() {
        System.out.println("Render a Windows style text box.");
    }
}

MacTextBox.java

java 复制代码
class MacTextBox implements TextBox {
    public void render() {
        System.out.println("Render a Mac style text box.");
    }
}

3. 定义抽象工厂接口

UIFactory.java

java 复制代码
public interface UIFactory {
    Button createButton();   // 创建按钮
    TextBox createTextBox(); // 创建文本框
}

4. 实现具体工厂类

WindowsFactory.java

java 复制代码
class WindowsFactory implements UIFactory {
    public Button createButton() {
        return new WindowsButton();
    }

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

MacFactory.java

java 复制代码
class MacFactory implements UIFactory {
    public Button createButton() {
        return new MacButton();
    }

    public TextBox createTextBox() {
        return new MacTextBox();
    }
}

5. 编写客户端代码使用抽象工厂

Client.java

java 复制代码
public class Client {
    private Button button;
    private TextBox textBox;

    public Client(UIFactory factory) {
        this.button = factory.createButton();
        this.textBox = factory.createTextBox();
    }

    public void renderUI() {
        button.render();
        textBox.render();
    }

    public static void main(String[] args) {
        String osType = "mac"; // 可改为 "windows"

        UIFactory factory;
        if ("windows".equalsIgnoreCase(osType)) {
            factory = new WindowsFactory();
        } else {
            factory = new MacFactory();
        }

        Client client = new Client(factory);
        client.renderUI();
    }
}

输出结果(当 osType = "mac")

css 复制代码
Render a Mac style button.
Render a Mac style text box.

总结
角色 类名
抽象产品A Button
抽象产品B TextBox
具体产品A1 WindowsButton
具体产品A2 MacButton
具体产品B1 WindowsTextBox
具体产品B2 MacTextBox
抽象工厂 UIFactory
具体工厂1 WindowsFactory
具体工厂2 MacFactory

扩展建议
  • 如果需要新增一个控件类型(如 ComboBox),只需在抽象工厂中添加新方法,并在所有具体工厂中实现。
  • 若使用 Java 8+,可在接口中提供默认实现,提高灵活性。
  • 结合 Spring 或其他 IOC 框架可以实现更优雅的解耦与配置切换。
相关推荐
轻语呢喃1 小时前
JavaScript :字符串模板——优雅编程的基石
前端·javascript·后端
MikeWe1 小时前
Paddle张量操作全解析:从基础创建到高级应用
后端
岫珩1 小时前
Ubuntu系统关闭防火墙的正确方式
后端
心之语歌2 小时前
Java高效压缩技巧:ZipOutputStream详解
java·后端
不死的精灵2 小时前
【Java21】在spring boot中使用ScopedValue
java·spring boot·后端
M1A13 小时前
TCP/IP协议精解:IP协议——互联网世界的邮政编码系统
后端·网络协议·tcp/ip
逸风尊者3 小时前
开发易掌握的知识:GeoHash查找附近空闲车辆
java·后端
程序猿阿越4 小时前
Kafka源码(一)Controller选举与创建Topic
java·后端·源码
程序员爱钓鱼4 小时前
Go语言项目工程化 — 常见开发工具与 CI/CD 支持
开发语言·后端·golang·gin
Jiude5 小时前
MinIO 社区版被故意阉割,Web管理功能全面移除。我来试试国产RustFS
后端·docker·架构