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() 方法即可。

public abstract class AbstractFolder {
    public abstract String getFolderPath(String orgId);
}

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

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 对象。

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 ,其代码和之前一样:

public abstract class AbstractFolder {
    public abstract String getFolderPath(String orgId);
}

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

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 对象。

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() 方法,用于创建抽象产品类的实例。

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

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 类相似:

public abstract class AbstractDepartmentFolder {
    public abstract String getDepartmentFolderPath(String orgId);
}

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

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

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() 用于创建部门文件夹和员工文件夹对应的产品。

public abstract class AbstractFolderFactory {
    public abstract AbstractDepartmentFolder createDepartmentFolder();
    public abstract AbstractEmployeeFolder createEmployeeFolder();
}

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

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();
    }
}

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

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() 方法。

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

相关推荐

  1. GPT-设计模式14-工厂模式

    2024-07-16 19:34:02       18 阅读
  2. GPT-设计模式11-组合模式

    2024-07-16 19:34:02       35 阅读
  3. GPT-设计模式12-状态模式

    2024-07-16 19:34:02       30 阅读
  4. GPT-设计模式-13策略模式

    2024-07-16 19:34:02       26 阅读
  5. 跟着GPT设计模式模板模式

    2024-07-16 19:34:02       21 阅读
  6. 跟着GPT设计模式之建造者模式

    2024-07-16 19:34:02       58 阅读
  7. 跟着GPT设计模式之原型模式

    2024-07-16 19:34:02       53 阅读
  8. 跟着GPT设计模式之观察者模式

    2024-07-16 19:34:02       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 19:34:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 19:34:02       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 19:34:02       58 阅读
  4. Python语言-面向对象

    2024-07-16 19:34:02       69 阅读

热门阅读

  1. InnoDB

    2024-07-16 19:34:02       21 阅读
  2. 跨入嵌入式day1(Linux下C语言-基础知识)

    2024-07-16 19:34:02       18 阅读
  3. sqlalchemy mapper的使用

    2024-07-16 19:34:02       17 阅读
  4. git初始化项目

    2024-07-16 19:34:02       18 阅读
  5. 有用的C语言相关函数

    2024-07-16 19:34:02       18 阅读
  6. P10781 【MX-J1-T1】『FLA - III』Spectral 题解

    2024-07-16 19:34:02       16 阅读
  7. docker镜像源配置

    2024-07-16 19:34:02       19 阅读
  8. React基础学习-Day05

    2024-07-16 19:34:02       17 阅读
  9. 每天一个数据分析题(四百三十一)- 卡方检验

    2024-07-16 19:34:02       21 阅读