GPT带我学-设计模式14-工厂模式

介绍

工厂模式(Factory Pattern)是一种常用的创建型设计模式,也叫做工厂方法模式(Factory Method Pattern),它提供了一种创建对象的最佳方式。在工厂模式中,我们不再直接通过 new 来创建对象,而是通过一个工厂类来间接地创建对象。主要包含以下几个角色:

  1. 抽象产品(Product):定义产品的接口或抽象类,具体产品由其子类实现。

  2. 具体产品(Concrete Product):实现抽象产品接口的具体类,是被创建的对象。

  3. 抽象工厂(Factory):提供创建产品对象的接口或抽象类,具体工厂由其子类实现。

  4. 具体工厂(Concrete Factory):实现抽象工厂接口的具体类,具有生产不同具体产品的能力。

使用工厂模式能够将对象的创建和使用分离,可以降低系统的耦合度,提高系统的可扩展性和可维护性。常见的应用场景包括日志记录器、数据库访问、窗口创建等。

类型

工厂模式通常分为三种类型:

  1. 简单工厂模式(Simple Factory Pattern):又称静态工厂方法模式,它由一个工厂类根据传入的参数决定创建出哪一种产品类的实例。简单工厂模式适用于产品种类较少且不经常变化的情况。

  2. 工厂方法模式(Factory Method Pattern):是针对简单工厂模式缺点而产生的。在工厂方法模式中,每个具体产品都对应一个具体工厂,每个具体工厂只能创建一个具体产品对象,但是可以通过添加新的具体工厂来创建新的具体产品。

  3. 抽象工厂模式(Abstract Factory Pattern):又称工具箱模式,提供一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类。抽象工厂模式适用于产品族和产品等级结构比较复杂的情况。

示例

场景,根据组织orgId,生成不同的文件夹路径。

简单工厂模式

好的,我可以为您提供一个基于简单工厂模式的实现,具体如下:

首先,我们需要定义抽象产品类 AbstractFolder ,用于描述文件夹的基本属性和功能。本例中,我们只需要使用其中的 getFolderPath() 方法即可。

java 复制代码
public abstract class AbstractFolder {
    public abstract String getFolderPath(String orgId);
}

接下来,我们需要创建两个具体产品类 DepartmentFolderEmployeeFolder ,它们分别代表组织机构的部门文件夹和员工文件夹,两个类都要实现 getFolderPath() 方法。

java 复制代码
public class DepartmentFolder extends AbstractFolder {
    @Override
    public String getFolderPath(String orgId) {
        return "organizations/" + orgId + "/departments/";
    }
}

public class EmployeeFolder extends AbstractFolder {
    @Override
    public String getFolderPath(String orgId) {
        return "organizations/" + orgId + "/employees/";
    }
}

最后,我们需要创建一个工厂类 FolderFactory ,用于根据传入参数 orgId 来创建对应的文件夹对象。当传入的 orgIdDEPARTMENT 时,返回 DepartmentFolder 对象;当传入的 orgIdEMPLOYEE 时,返回 EmployeeFolder 对象。

java 复制代码
public class FolderFactory {
    public static AbstractFolder createFolder(String orgId) {
        if ("DEPARTMENT".equals(orgId)) {
            return new DepartmentFolder();
        } else if ("EMPLOYEE".equals(orgId)) {
            return new EmployeeFolder();
        } else {
            throw new IllegalArgumentException("Invalid orgId: " + orgId);
        }
    }
}

这样,当调用 FolderFactory.createFolder("DEPARTMENT").getFolderPath("company") 时,会返回 "organizations/company/departments/" 的字符串,调用 FolderFactory.createFolder("EMPLOYEE").getFolderPath("company") 时,会返回 "organizations/company/employees/" 的字符串。

希望这个示例能够帮助您理解如何使用简单工厂模式实现您的需求。

工厂方法模式

好的,针对您的需求,我们可以把简单工厂模式改为工厂方法模式。工厂方法模式中,每个具体产品类都有一个对应的工厂类,用于创建该产品类的实例。

首先,我们仍然需要定义抽象产品类 AbstractFolder ,其代码和之前一样:

java 复制代码
public abstract class AbstractFolder {
    public abstract String getFolderPath(String orgId);
}

接下来,我们需要创建两个具体产品类 DepartmentFolderEmployeeFolder ,它们分别代表组织机构的部门文件夹和员工文件夹,两个类依然都要实现 getFolderPath() 方法,与之前一致:

java 复制代码
public class DepartmentFolder extends AbstractFolder {
    @Override
    public String getFolderPath(String orgId) {
        return "organizations/" + orgId + "/departments/";
    }
}

public class EmployeeFolder extends AbstractFolder {
    @Override
    public String getFolderPath(String orgId) {
        return "organizations/" + orgId + "/employees/";
    }
}

接下来是关键的部分:我们需要创建两个工厂类 DepartmentFolderFactoryEmployeeFolderFactory,它们分别用于创建 DepartmentFolderEmployeeFolder 对象。

java 复制代码
public class DepartmentFolderFactory implements FolderFactory {
    @Override
    public AbstractFolder createFolder() {
        return new DepartmentFolder();
    }
}

public class EmployeeFolderFactory implements FolderFactory {
    @Override
    public AbstractFolder createFolder() {
        return new EmployeeFolder();
    }
}

这里的 FolderFactory 是一个接口,其中定义了一个 createFolder() 方法,用于创建抽象产品类的实例。

最后,我们需要让客户端使用这些工厂类创建对象。客户端只需要知道要创建哪种类型的文件夹,在运行时再传入对应的工厂类即可。

java 复制代码
public interface FolderFactory {
    AbstractFolder createFolder();
}


public class Client {
    public static void main(String[] args) {
        String orgId = "company";
        FolderFactory departmentFactory = new DepartmentFolderFactory();
        AbstractFolder departmentFolder = departmentFactory.createFolder();
        System.out.println(departmentFolder.getFolderPath(orgId));
        
        FolderFactory employeeFactory = new EmployeeFolderFactory();
        AbstractFolder employeeFolder = employeeFactory.createFolder();
        System.out.println(employeeFolder.getFolderPath(orgId));
    }
}

这个示例中,我们通过两个工厂类分别创建了部门文件夹和员工文件夹,并调用了它们的 getFolderPath() 方法。

希望这个示例能够帮助您理解如何使用工厂方法模式实现您的需求。

抽象工厂模式

好的,针对您的需求,我们可以把工厂方法模式改为抽象工厂模式。在抽象工厂模式中,一个工厂类可以创建多个产品族(相关联的一组产品),而在工厂方法模式中,一个工厂类只能创建同一产品等级结构(一类产品)的产品。

首先,我们需要定义两个抽象产品类 AbstractDepartmentFolderAbstractEmployeeFolder ,其代码和之前的 AbstractFolder 类相似:

java 复制代码
public abstract class AbstractDepartmentFolder {
    public abstract String getDepartmentFolderPath(String orgId);
}

public abstract class AbstractEmployeeFolder {
    public abstract String getEmployeeFolderPath(String orgId);
}

接下来,我们需要创建两个具体产品类 DepartmentFolderEmployeeFolder ,它们分别实现 AbstractDepartmentFolderAbstractEmployeeFolder 接口,依然分别代表部门文件夹和员工文件夹,代码如下:

java 复制代码
public class DepartmentFolder implements AbstractDepartmentFolder {
    @Override
    public String getDepartmentFolderPath(String orgId) {
        return "organizations/" + orgId + "/departments/";
    }
}

public class EmployeeFolder implements AbstractEmployeeFolder {
    @Override
    public String getEmployeeFolderPath(String orgId) {
        return "organizations/" + orgId + "/employees/";
    }
}

然后,我们需要定义一个抽象工厂类 AbstractFolderFactory 来创建 AbstractDepartmentFolderAbstractEmployeeFolder 两个产品族。其中定义了两个工厂方法 createDepartmentFolder()createEmployeeFolder() 用于创建部门文件夹和员工文件夹对应的产品。

java 复制代码
public abstract class AbstractFolderFactory {
    public abstract AbstractDepartmentFolder createDepartmentFolder();
    public abstract AbstractEmployeeFolder createEmployeeFolder();
}

接下来,我们创建两个具体工厂类 DefaultFolderFactoryCustomizedFolderFactory ,分别对应默认的文件夹路径和定制化的文件夹路径。这两个具体工厂类实现了抽象工厂类中的两个工厂方法,分别创建 DepartmentFolderEmployeeFolder 对象。

java 复制代码
public class DefaultFolderFactory extends AbstractFolderFactory {
    @Override
    public AbstractDepartmentFolder createDepartmentFolder() {
        return new DepartmentFolder();
    }

    @Override
    public AbstractEmployeeFolder createEmployeeFolder() {
        return new EmployeeFolder();
    }
}

public class CustomizedFolderFactory extends AbstractFolderFactory {
    @Override
    public AbstractDepartmentFolder createDepartmentFolder() {
        // 这里是定制化的部门文件夹路径
        return new DepartmentFolderCustomized();
    }

    @Override
    public AbstractEmployeeFolder createEmployeeFolder() {
        // 这里是定制化的员工文件夹路径
        return new EmployeeFolderCustomized();
    }
}

最后,我们需要让客户端使用这些工厂类创建对象。客户端只需要知道要创建哪种类型的工厂,在运行时再传入对应的工厂即可。

java 复制代码
public class Client {
    public static void main(String[] args) {
        String orgId = "company";
        AbstractFolderFactory defaultFactory = new DefaultFolderFactory();
        AbstractDepartmentFolder departmentFolder = defaultFactory.createDepartmentFolder();
        AbstractEmployeeFolder employeeFolder = defaultFactory.createEmployeeFolder();
        System.out.println(departmentFolder.getDepartmentFolderPath(orgId));
        System.out.println(employeeFolder.getEmployeeFolderPath(orgId));

        AbstractFolderFactory customizedFactory = new CustomizedFolderFactory();
        AbstractDepartmentFolder customizedDepartmentFolder = customizedFactory.createDepartmentFolder();
        AbstractEmployeeFolder customizedEmployeeFolder = customizedFactory.createEmployeeFolder();
        System.out.println(customizedDepartmentFolder.getDepartmentFolderPath(orgId));
        System.out.println(customizedEmployeeFolder.getEmployeeFolderPath(orgId));
    }
}

这个示例中,我们通过两个抽象工厂类分别创建默认的和定制化的文件夹路径,然后分别使用 createDepartmentFolder()createEmployeeFolder() 方法创建部门文件夹和员工文件夹,并调用它们的 getDepartmentFolderPath()getEmployeeFolderPath() 方法。

希望这个示例能够帮助您理解如何使用抽象工厂模式实现您的需求。

相关推荐
陈小桔10 小时前
idea中重新加载所有maven项目失败,但maven compile成功
java·maven
小学鸡!10 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
xiaogg367810 小时前
阿里云k8s1.33部署yaml和dockerfile配置文件
java·linux·kubernetes
逆光的July11 小时前
Hikari连接池
java
微风粼粼11 小时前
eclipse 导入javaweb项目,以及配置教程(傻瓜式教学)
java·ide·eclipse
番茄Salad11 小时前
Spring Boot临时解决循环依赖注入问题
java·spring boot·spring cloud
天若有情67311 小时前
Spring MVC文件上传与下载全面详解:从原理到实战
java·spring·mvc·springmvc·javaee·multipart
祈祷苍天赐我java之术11 小时前
Redis 数据类型与使用场景
java·开发语言·前端·redis·分布式·spring·bootstrap
Olrookie12 小时前
若依前后端分离版学习笔记(二十)——实现滑块验证码(vue3)
java·前端·笔记·后端·学习·vue·ruoyi
倚栏听风雨13 小时前
java.lang.SecurityException异常
java