java 设计模式 工厂模式

什么是工厂模式

工厂模式(Factory Pattern)是一种创建型 设计模式,它通过定义一个接口或抽象类 来创建对象,但由子类决定 具体实例 化哪个类。简单来说,工厂模式将对象的实例化过程封装 起来,客户端通过工厂方法来创建对象,而不需要直接使用 new 关键字。

工厂模式的目的 是将对象的创建和使用解耦,使得客户端代码不需要关心具体对象的创建过程,尤其是对象的构造方式或者具体类型。

工厂模式的作用

  1. 解耦:客户端代码与具体的对象创建解耦,客户端只需要依赖工厂接口而不依赖具体的实现类。
  2. 代码重用:工厂方法可以提供统一的创建对象的逻辑,从而避免重复代码。
  3. 更好的扩展性:如果系统中需要新增不同的产品类,只需要添加新的工厂类即可,不需要修改原有的客户端代码。
  4. 灵活的对象管理:有些工厂模式可以实现对象的缓存或对象池,从而优化性能。

示例

不使用工厂模式获取实例

java 复制代码
// 抽象产品:Button(按钮)
interface Button {
    void render();
}

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

// 具体产品:MacButton(Mac 按钮)
class MacButton implements Button {
    @Override
    public void render() {
        System.out.println("Rendering a Mac Button");
    }
}

// 客户端代码:根据操作系统类型选择不同按钮
public class Main {
    public static void main(String[] args) {
        Button button;
        String osType = "Windows";  // 假设从配置中获取操作系统类型

        if ("Windows".equalsIgnoreCase(osType)) {
            button = new WindowsButton();
        } else {
            button = new MacButton();
        }

        button.render();
    }
}

这里如果又新增一个liunx按钮 客户端又要重新修改代码

使用工厂模式

java 复制代码
// 抽象产品:Button(按钮)
interface Button {
    void render();
}

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

// 具体产品:MacButton(Mac 按钮)
class MacButton implements Button {
    @Override
    public void render() {
        System.out.println("Rendering a Mac Button");
    }
}

// 具体产品:LinuxButton(Linux 按钮)
class LinuxButton implements Button {
    @Override
    public void render() {
        System.out.println("Rendering a Linux Button");
    }
}

// 抽象工厂:GUIFactory
interface GUIFactory {
    Button createButton();
}

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

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

// 具体工厂:LinuxFactory
class LinuxFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new LinuxButton();
    }
}

// 工厂创建器:根据操作系统类型选择对应的工厂
class FactoryCreator {
    public static GUIFactory getFactory(String osType) {
        if ("Windows".equalsIgnoreCase(osType)) {
            return new WindowsFactory();
        } else if ("Mac".equalsIgnoreCase(osType)) {
            return new MacFactory();
        } else if ("Linux".equalsIgnoreCase(osType)) {
            return new LinuxFactory();
        }
        return null;
    }
}

// 客户端代码:通过工厂创建按钮
public class Main {
    public static void main(String[] args) {
        // 假设从配置文件或环境变量获取操作系统类型
        String osType = System.getProperty("os.name"); // 获取操作系统名称(例如:Windows、Mac、Linux)

        // 使用工厂创建器自动选择工厂
        GUIFactory factory = FactoryCreator.getFactory(osType);
        
        // 通过工厂创建按钮
        if (factory != null) {
            Button button = factory.createButton();
            button.render();
        } else {
            System.out.println("No suitable factory found for " + osType);
        }
    }
}

这里你无论新增多少按钮,客户端代码始终不变

工厂模式的种类

简单工厂模式(Simple Factory Pattern)

通过一个工厂类来根据参数的不同返回不同类型的对象。
优点 :客户端代码很简单,所有的产品类都集中在一个地方。
缺点:如果产品类增多,工厂类需要做出改动,违反了开放-封闭原则。

示例

产品类

java 复制代码
class Car {
    void drive() {
        System.out.println("Driving a car");
    }
}

class Truck {
    void drive() {
        System.out.println("Driving a truck");
    }
}

工厂类

java 复制代码
class VehicleFactory {
    public static Object createVehicle(String type) {
        if (type.equals("car")) {
            return new Car();
        } else if (type.equals("truck")) {
            return new Truck();
        }
        return null;
    }
}
java 复制代码
public class Main {
    public static void main(String[] args) {
        Object vehicle = VehicleFactory.createVehicle("car");
        if (vehicle instanceof Car) {
            ((Car) vehicle).drive();
        }
    }
}

工厂方法模式(Factory Method Pattern)

定义一个创建对象的接口,但让子类决定实例化哪个类。这样,工厂方法模式允许子类来决定返回什么样的对象,而不需要修改客户端代码。

优点:符合开放-封闭原则,产品扩展时不需要修改客户端代码。

简单来说,就是有个产品,咱们需要定义一个接口或者抽象类定义需要实现的方法(例如开车),然后创建多个具体类实现或者继承该方法去实现不同的开车类型(开卡车,开拖拉机,开小车),有了具体的类之后,需要创建工厂帮我们创建开车类型,这里比简单工厂模式优化点是,创建一了一个抽象工厂,让下面的子类具体工厂继承抽象工厂来帮我们实现具体的产品。这样符合开闭原则了

产品类

java 复制代码
interface Vehicle {
    void drive();
}

class Car implements Vehicle {
    @Override
    public void drive() {
        System.out.println("Driving a car");
    }
}

class Truck implements Vehicle {
    @Override
    public void drive() {
        System.out.println("Driving a truck");
    }
}

工厂类

java 复制代码
abstract class VehicleFactory {
    abstract Vehicle createVehicle();
}

class CarFactory extends VehicleFactory {
    @Override
    Vehicle createVehicle() {
        return new Car();
    }
}

class TruckFactory extends VehicleFactory {
    @Override
    Vehicle createVehicle() {
        return new Truck();
    }
}
java 复制代码
public class Main {
    public static void main(String[] args) {
        VehicleFactory factory = new CarFactory();
        Vehicle vehicle = factory.createVehicle();
        vehicle.drive();
    }
}

抽象工厂模式

提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。

工厂方法模式创建的是单个对象,而抽象工厂模式创建的是多个相关对象。

简单来说抽象工厂就是有几个配套的抽象产品 (车轮和车胎),多个具体的类实现不同的抽象产品 (车轮和车胎)当成具体实现类(越野车胎,越野车轮,公路车胎,公路车轮),有了这些类之后,需要实现工厂来帮我们进行组合,所有有个抽象工厂类 用来创建车胎和车轮,然后创建具体的工厂实现抽象工厂,来返回配套的车胎车轮。

示例

产品类

java 复制代码
// 抽象产品:车轮
interface Wheel {
    void create();
}

// 抽象产品:轮胎
interface Tire {
    void create();
}

// 具体产品:越野车轮
class OffRoadWheel implements Wheel {
    @Override
    public void create() {
        System.out.println("Creating Off-road Wheel");
    }
}

// 具体产品:公路车轮
class RoadWheel implements Wheel {
    @Override
    public void create() {
        System.out.println("Creating Road Wheel");
    }
}

// 具体产品:越野轮胎
class OffRoadTire implements Tire {
    @Override
    public void create() {
        System.out.println("Creating Off-road Tire");
    }
}

// 具体产品:公路轮胎
class RoadTire implements Tire {
    @Override
    public void create() {
        System.out.println("Creating Road Tire");
    }
}

工厂类

java 复制代码
// 抽象工厂:车轮和轮胎的工厂
interface VehiclePartsFactory {
    Wheel createWheel();
    Tire createTire();
}

// 具体工厂:越野车配件工厂
class OffRoadVehiclePartsFactory implements VehiclePartsFactory {
    @Override
    public Wheel createWheel() {
        return new OffRoadWheel();
    }

    @Override
    public Tire createTire() {
        return new OffRoadTire();
    }
}

// 具体工厂:公路车配件工厂
class RoadVehiclePartsFactory implements VehiclePartsFactory {
    @Override
    public Wheel createWheel() {
        return new RoadWheel();
    }

    @Override
    public Tire createTire() {
        return new RoadTire();
    }
}
java 复制代码
// 客户端代码
public class Main {
    public static void main(String[] args) {
        // 创建越野车配件工厂
        VehiclePartsFactory offRoadFactory = new OffRoadVehiclePartsFactory();
        Wheel offRoadWheel = offRoadFactory.createWheel();
        Tire offRoadTire = offRoadFactory.createTire();
        offRoadWheel.create();
        offRoadTire.create();

        // 创建公路车配件工厂
        VehiclePartsFactory roadFactory = new RoadVehiclePartsFactory();
        Wheel roadWheel = roadFactory.createWheel();
        Tire roadTire = roadFactory.createTire();
        roadWheel.create();
        roadTire.create();
    }
}

springboot哪些地方使用了工厂模式

BeanFactory 和 ApplicationContext

Spring 提供了 BeanFactory 和 ApplicationContext 作为工厂类来管理 bean 的创建和生命周期。这两个接口实际上是工厂模式的应用,ApplicationContext 扩展了 BeanFactory,用于创建和管理应用程序中的 bean。

示例

java 复制代码
@Configuration
public class AppConfig {
    @Bean
    public Car car() {
        return new Car();
    }
}

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Car car = context.getBean(Car.class);
        car.drive();
    }
}

FactoryBean

FactoryBean 是一个工厂类,但是它并不是直接返回一个简单的对象,而是返回一个由 FactoryBean 实现逻辑控制的复杂对象。

示例

这里可以对比之前的工厂模式,可以看出就是工厂模式(有产品类,有工厂类,有具体工厂实现)

java 复制代码
public class Car {
    public void drive() {
        System.out.println("Driving the car!");
    }
}

public class CarFactoryBean implements FactoryBean<Car> {

    @Override
    public Car getObject() throws Exception {
        // 在这里可以写复杂的创建逻辑
        System.out.println("Creating Car object via FactoryBean");
        return new Car();
    }

    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        return true;  // 返回单例
    }
}

JdbcTemplate

JdbcTemplate 是 Spring 中的一个工具类,它通过工厂模式封装了数据库连接的创建过程,并提供了统一的操作接口。开发者无需关心底层数据库连接的具体实现。

何时使用工厂模式?

需要隐藏对象创建的复杂性 当对象的创建过程复杂时,直接使用 new 关键字可能会导致代码重复、易出错、难以维护。通过工厂模式,可以将对象创建的过程封装到工厂类中,客户端代码不需要关心如何创建对象,而只需要关心如何使用对象。

需要创建的对象有多个子类 当你需要创建的对象有多个具体实现类,而这些类的具体实现对客户端不重要时,可以通过工厂模式来集中管理这些不同的对象创建过程。工厂模式能够根据不同的参数或条件动态决定实例化哪个具体的类。

对象的创建过程可能会变化或扩展 当系统需要支持未来扩展(例如,新增产品类或功能)时,使用工厂模式可以避免修改已有代码,只需要扩展工厂类来支持新的对象创建。工厂模式遵循 开放-封闭原则,便于扩展而不需要修改现有的客户端代码。

需要依赖注入和对象管理 在一些框架(如 Spring)中,工厂模式用于创建和管理对象,例如 BeanFactory 和 ApplicationContext 就是通过工厂模式来管理对象的生命周期和依赖关系。

简单来说

相关推荐
上位机付工5 分钟前
开源免费的上位机数据转换库
开发语言·c#
学习前端的小z6 分钟前
【C++】B2112 石头剪子布
开发语言·c++
二当家的素材网7 分钟前
一分钟学会文心一言API如何接入,文心一言API接入教程
开发语言·语言模型·文心一言
猿猴一号(lxd)12 分钟前
java根据模板导出word,并在word中插入echarts相关统计图片以及表格
java·word·echarts
小桑要读研22 分钟前
二级缓存(缓存到Redis)
java·开发语言·spring
诺谦26 分钟前
3.Qt Quick-QML地图引擎之v4.3版本(新增动态轨迹线/海图/天地图街道/天地图卫星)
开发语言·qt
晴子呀34 分钟前
单例模式的几种实现方式
java·开发语言
脸红ฅฅ*的思春期42 分钟前
JAVA安全—JWT攻防&Swagger自动化&Druid泄露
java·安全·自动化·jwt
时雨h1 小时前
[Java Web] 第四章 XML_Tomcat10_HTTP
java
有杨既安然1 小时前
Python爬取豆瓣图书网Top250 实战
开发语言·爬虫·python·网络爬虫·爬虫实战