工厂模式详解

1.简单工厂模式

简单工厂模式(Simple Factory Pattern)并不是一种标准的设计模式(不在GoF设计模式的23种之列),而是一种编程习惯,用于创建对象而不必指定将要创建的对象的确切类。它有一个工厂类,可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类和接口。

  • 优点:将对象的创建和使用分离,客户端无需知道具体的实现类,只需要知道工厂类。
  • 缺点:工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违反了开闭原则。

首先,定义一个接口或抽象类来规范产品对象的行为。

public interface Product {
    void use();
}

然后,实现具体的产品类。

public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductA");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductB");
    }
}

接下来,创建一个工厂类来生成基于给定信息的具体产品对象。

public 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 productA = factory.createProduct("A");
        productA.use();

        Product productB = factory.createProduct("B");
        productB.use();
    }
}

在这个例子中,SimpleFactory 类根据传入的参数(例如,类型"A"或"B")决定实例化哪一个具体产品类(ConcreteProductAConcreteProductB)。客户端不需要直接实例化产品对象,而是通过工厂类来请求创建对象,这样就降低了客户端与具体产品类之间的耦合度。简单工厂模式适用于产品种类不太复杂,且不频繁添加新产品的情况。

2.工厂方法模式

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行。

  • 优点:在添加新的产品时不需要修改已有的工厂类,只需添加相应的产品类和具体工厂类即可,满足开闭原则。
  • 缺点:每增加一个产品,就需要增加一个具体产品类和一个具体工厂类,增加了系统的复杂度。

在以下的例子中,将通过一个简单的日志记录器的例子来演示如何实现工厂方法模式。这个例子包括一个Logger接口和两个实现了这个接口的具体日志记录器类(FileLoggerConsoleLogger),以及一个LoggerFactory接口和为每种日志记录器提供创建功能的具体工厂类。

首先,定义Logger接口和两个具体的日志记录器类:

// 日志记录器接口
public interface Logger {
    void log(String message);
}

// 将消息记录到控制台的具体日志记录器
public class ConsoleLogger implements Logger {
    public void log(String message) {
        System.out.println("ConsoleLogger: " + message);
    }
}

// 将消息记录到文件的具体日志记录器
public class FileLogger implements Logger {
    public void log(String message) {
        System.out.println("FileLogger: " + message);
    }
}

接下来,定义LoggerFactory接口和具体的工厂类:

// 日志记录器工厂接口
public interface LoggerFactory {
    Logger createLogger();
}

// 创建控制台日志记录器的工厂
public class ConsoleLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
        // 创建一个新的控制台日志记录器实例
        return new ConsoleLogger();
    }
}

// 创建文件日志记录器的工厂
public class FileLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
        // 创建一个新的文件日志记录器实例
        return new FileLogger();
    }
}

最后,客户端代码利用工厂来创建日志记录器:

public class Client {
    public static void main(String[] args) {
        LoggerFactory factory;
        Logger logger;

        // 使用控制台日志记录器
        factory = new ConsoleLoggerFactory();
        logger = factory.createLogger();
        logger.log("This is a message.");

        // 使用文件日志记录器
        factory = new FileLoggerFactory();
        logger = factory.createLogger();
        logger.log("This is another message.");
    }
}

在这个例子中,LoggerFactory定义了一个创建对象的方法createLogger,而具体的工厂类(ConsoleLoggerFactoryFileLoggerFactory)实现了这个方法来创建具体类型的日志记录器。这样,客户端代码就可以在不知道具体日志记录器类的情况下,通过工厂接口来创建日志记录器对象。这种方式使得添加新的日志记录器类型时,客户端代码不需要做任何修改,符合开闭原则。

3.抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。这种模式特别适用于那些系统中,有多个系列的产品需要创建,并且系统需要在多个系列产品之间切换时。该模式允许客户端使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)具体产品的具体类。

  • 优点:可以在类内部对产品族的相关对象进行组合,更易于交换产品系列,并保证其兼容性。
  • 缺点:难以支持新种类的(产品),扩展新的产品族困难,需要修改抽象工厂的接口。

下面是一个简单的Java实现示例,假设有一个GUI元素的库,其中包括按钮和复选框,这些GUI元素有不同的风格(如Windows和Mac风格)。我们将使用抽象工厂模式来抽象和封装这些元素的创建过程。

首先,定义抽象产品接口和具体产品类:

// 抽象产品:按钮
public interface Button {
    void paint();
}

// 具体产品:Windows风格按钮
public class WindowsButton implements Button {
    public void paint() {
        System.out.println("Rendering a button in Windows style.");
    }
}

// 具体产品:Mac风格按钮
public class MacButton implements Button {
    public void paint() {
        System.out.println("Rendering a button in Mac style.");
    }
}

// 抽象产品:复选框
public interface Checkbox {
    void paint();
}

// 具体产品:Windows风格复选框
public class WindowsCheckbox implements Checkbox {
    public void paint() {
        System.out.println("Rendering a checkbox in Windows style.");
    }
}

// 具体产品:Mac风格复选框
public class MacCheckbox implements Checkbox {
    public void paint() {
        System.out.println("Rendering a checkbox in Mac style.");
    }
}

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

// 抽象工厂
public interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 具体工厂:Windows风格工厂
public class WindowsFactory implements GUIFactory {
    public Button createButton() {
        return new WindowsButton();
    }

    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

// 具体工厂:Mac风格工厂
public class MacFactory implements GUIFactory {
    public Button createButton() {
        return new MacButton();
    }

    public Checkbox createCheckbox() {
        return new MacCheckbox();
    }
}

最后,客户端代码可能看起来像这样:

public class Application {
    private Button button;
    private Checkbox checkbox;

    public Application(GUIFactory factory) {
        button = factory.createButton();
        checkbox = factory.createCheckbox();
    }

    public void paint() {
        button.paint();
        checkbox.paint();
    }

    public static void main(String[] args) {
        GUIFactory factory = new WindowsFactory();
        Application app = new Application(factory);
        app.paint();
        
        // 切换到Mac风格
        factory = new MacFactory();
        app = new Application(factory);
        app.paint();
    }
}

在这个例子中,Application类不直接依赖于具体的按钮或复选框类(如WindowsButtonMacCheckbox),而是通过GUIFactory接口来创建这些对象。这样,通过更换不同的GUIFactory实现(如WindowsFactoryMacFactory),就可以在不同的GUI风格之间切换,而无需修改Application类的代码。这就是抽象工厂模式的魅力。

4.区别总结

  • 应用层次不同:简单工厂模式适合产品种类较少的情况;工厂方法模式适用于一个类别下有多个种类的情况;抽象工厂模式适用于有多个产品族,且产品族中有多个种类的情况。
  • 复杂度增加:从简单工厂到工厂方法,再到抽象工厂,设计的复杂度和理解难度是逐步增加的。
  • 抽象级别:简单工厂模式的抽象级别最低,抽象工厂模式的抽象级别最高,工厂方法模式居中。
  • 灵活性和可扩展性:简单工厂模式的灵活性和可扩展性最差,抽象工厂模式最好,工厂方法模式居中。
  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值