【设计模式】工厂模式(创建型)⭐⭐⭐

1.概念

1.1 什么是工厂模式

工厂模式属于创建型模式。它的主要目的是提供一个创建对象的接口,而不直接实例化对象。这样可以将对象的创建和使用分离,降低系统的耦合度,提高系统的灵活性和可扩展性。

1.2 优点与缺点

优点:
1.降低了系统中对象的耦合度,提高了系统的灵活性。
2.增加了系统的可扩展性,当增加新的产品时,只需扩展一个工厂类即可。
3.隔离了具体产品的创建,使得代码符合单一职责原则。
缺点:
1.增加了系统的复杂度,因为引入了新的工厂类层次。
2.如果产品等级结构过于复杂,那么工厂方法模式的类层次也会相当复杂。

2.实现方式

2.1 简单工厂模式(Simple Factory)

① 定义产品接口或抽象类

public interface Product {
    void operate();
}

② 实现具体产品类:接着,我们创建具体的产品类,它们实现了产品接口或继承了抽象类。

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

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

③ 创建工厂类:然后,我们创建一个工厂类,它提供一个静态方法来创建产品对象。工厂方法根据传入的参数来决定创建哪个具体产品类的实例。

public class SimpleFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        }
        return null;
    }
}

④ 客户端代码:最后,客户端代码通过调用工厂类的静态方法来获取产品实例,而不是直接创建产品对象。

public class Client {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        Product productB = SimpleFactory.createProduct("B");

        productA.operate();
        productB.operate();
    }
}

这种实现方式使得客户端代码与具体产品类的实现解耦,提高了系统的灵活性和可扩展性。如果需要增加新的产品类,只需要扩展新的具体产品类,并在工厂类中增加相应的创建逻辑,而不需要修改客户端代码。

2.2 简单工厂模式缺点

违反开闭原则:简单工厂模式的工厂方法集中了所有产品的创建逻辑。当需要增加新的产品时,必须修改工厂方法来实现新的逻辑,这违反了开闭原则(软件实体应该对扩展开放,对修改关闭)。
工厂方法单一职责原则:随着产品种类增加,工厂方法会变得越来越复杂,包含大量的条件分支语句。这使得工厂类承担了过多的责任,违反了单一职责原则(一个类应该只有一个引起它变化的原因)。
扩展困难:由于工厂类集中了所有产品的创建逻辑,当产品种类很多时,工厂类会变得非常庞大,难以维护和扩展。
依赖集中:客户端代码依赖于工厂类,如果工厂类发生变化,可能会影响到客户端代码。
不利于产品类的解耦:虽然简单工厂模式将客户端的创建逻辑和产品类的实现解耦,但是产品类和工厂类之间的耦合度仍然较高,因为工厂类需要知道所有产品类的具体实现。
不利于反射和依赖注入:由于工厂类内部硬编码了产品类的创建逻辑,这使得在运行时难以通过反射或依赖注入的方式来动态地创建和替换产品对象。

2.3 抽象工厂模式(Abstract Factory Pattern)

① 定义抽象工厂接口:声明了一组用于创建抽象产品对象的方法。

public interface AbstractFactory {
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}

② 实现具体工厂类:实现了抽象工厂接口,每个具体工厂都负责创建自己产品系列中的对象。

public class ConcreteFactory1 implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

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

public class ConcreteFactory2 implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }

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

③ 定义抽象产品接口:声明了产品的公共接口。

public interface AbstractProductA {
    void usefulFunctionA();
}

public interface AbstractProductB {
    void usefulFunctionB();
}

④ 实现具体产品类:实现了抽象产品接口,每个具体产品都属于一个产品系列。

public class ConcreteProductA1 implements AbstractProductA {
    @Override
    public void usefulFunctionA() {
        // 具体实现
    }
}

public class ConcreteProductA2 implements AbstractProductA {
    @Override
    public void usefulFunctionA() {
        // 具体实现
    }
}

public class ConcreteProductB1 implements AbstractProductB {
    @Override
    public void usefulFunctionB() {
        // 具体实现
    }
}

public class ConcreteProductB2 implements AbstractProductB {
    @Override
    public void usefulFunctionB() {
        // 具体实现
    }
}

⑤ 客户端代码:客户端通过抽象工厂接口来创建产品,而不需要关心具体工厂和产品的实现细节。

public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        AbstractProductB productB1 = factory1.createProductB();
        productA1.usefulFunctionA();
        productB1.usefulFunctionB();

        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        AbstractProductB productB2 = factory2.createProductB();
        productA2.usefulFunctionA();
        productB2.usefulFunctionB();
    }
}

3. Java 哪些地方用到了工厂模式

Java AWT(Abstract Window Toolkit):AWT中的 Button, TextField, Label 等组件在不同的操作系统上会有不同的外观和行为。AWT使用抽象工厂模式来创建这些组件,以便它们可以根据运行平台的不同而自动适配。
Java Swing:与AWT类似,Swing组件也使用了抽象工厂模式来创建组件,以便它们可以根据不同的Look and Feel(比如Windows, Motif, Metal等)来改变外观。
JDBC(Java Database Connectivity):JDBC使用抽象工厂模式来创建数据库连接。DriverManager 类充当抽象工厂,它根据URL的不同来创建不同数据库的连接(例如MySQL, Oracle, SQL Server等)。
Java XML解析:在解析XML文档时,可以使用抽象工厂模式来创建不同的解析器。例如,可以根据需要创建SAX或DOM解析器的实例。
Java国际化(Internationalization, I18N):在处理国际化时,可以使用抽象工厂模式来创建不同语言环境的资源包。
Java Logging API:Java的日志记录框架(如Log4j, SLF4J等)通常使用抽象工厂模式来创建日志记录器实例,以便可以根据配置动态地选择不同的日志实现。
Spring Framework:Spring框架广泛使用了抽象工厂模式来创建bean。例如,BeanFactory 和 ApplicationContext 都是抽象工厂,它们负责根据配置文件或注解来创建和管理bean的生命周期。
Java ImageIO:ImageIO 类是一个抽象工厂,用于创建图像输入/输出处理的流。它可以根据图像格式(如JPEG, PNG, GIF等)来创建相应的图像读取器和写入器。

4. Spring 哪些地方用到了工厂模式

BeanFactory:BeanFactory 是Spring中最基本的抽象,它是一个工厂模式的实现,负责创建和管理bean的生命周期。BeanFactory 根据配置信息来创建bean,并且可以管理bean之间的依赖关系。
ApplicationContext:ApplicationContext 是 BeanFactory 的超集,它也实现了工厂模式。与 BeanFactory 相比,ApplicationContext 提供了更多的功能,如事件传播、资源加载、国际化消息处理等。
FactoryBean:Spring提供了一个名为 FactoryBean 的接口,允许开发者创建自己的工厂来生成复杂的对象。实现这个接口的类可以作为工厂,Spring容器会调用其 getObject 方法来获取bean实例。
ObjectFactory:ObjectFactory 是一个简单的工厂接口,它只有一个方法 getObject。这个接口通常用于延迟加载场景,可以在需要的时候才创建对象。
JdbcTemplate 和数据源:Spring的 JdbcTemplate 类依赖于数据源来获取数据库连接。数据源的创建通常是通过工厂模式来实现的,可以根据配置动态地创建不同类型的数据源实例。
事务管理:Spring的事务管理也使用了工厂模式。例如,TransactionManager 是一个抽象工厂,它根据配置来创建和管理事务。
AOP代理创建:Spring的AOP框架使用工厂模式来创建代理对象。根据配置的不同,Spring可以创建JDK动态代理或CGLIB代理。
消息服务:Spring的JMS模块使用工厂模式来创建消息生产者和消费者。
资源加载:Spring的 ResourceLoader 是一个抽象工厂,它根据资源路径来创建 Resource 对象。
事件发布:Spring的事件发布机制也使用了工厂模式,ApplicationEventPublisher 负责创建和发布事件。
Spring框架的设计哲学之一就是依赖注入(DI),它允许将对象之间的依赖关系外部化,由容器来管理。工厂模式是实现依赖注入的关键机制之一,它允许Spring容器根据配置来创建和管理对象,从而提供了极大的灵活性和扩展性。

相关推荐

  1. 设计模式工厂模式创建

    2024-06-05 20:18:05       8 阅读
  2. 设计模式】单例模式创建

    2024-06-05 20:18:05       8 阅读
  3. 设计模式】观察者模式(行为

    2024-06-05 20:18:05       7 阅读
  4. 设计模式】适配器模式(结构

    2024-06-05 20:18:05       7 阅读
  5. 设计模式】责任链模式(行为

    2024-06-05 20:18:05       8 阅读
  6. 设计模式】策略模式(行为

    2024-06-05 20:18:05       7 阅读
  7. 设计模式】装饰器模式(结构

    2024-06-05 20:18:05       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-05 20:18:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-05 20:18:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-05 20:18:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-05 20:18:05       18 阅读

热门阅读

  1. 封装PHP用于发送GET和POST请求的公共方法

    2024-06-05 20:18:05       10 阅读
  2. Elasticsearch 认证模拟题 - 6

    2024-06-05 20:18:05       7 阅读
  3. Elasticsearch (ES)内存管理降低内存占用率

    2024-06-05 20:18:05       7 阅读
  4. 高通Android 12/13实现USB拔出关机功能

    2024-06-05 20:18:05       7 阅读
  5. git命令

    git命令

    2024-06-05 20:18:05      8 阅读