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

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

相关推荐
繁依Fanyi6 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
慧都小妮子17 分钟前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net
m512721 分钟前
LinuxC语言
java·服务器·前端
IU宝26 分钟前
C/C++内存管理
java·c语言·c++
瓜牛_gn26 分钟前
依赖注入注解
java·后端·spring
hakesashou27 分钟前
Python中常用的函数介绍
java·网络·python
佚先森36 分钟前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html
小白不太白95040 分钟前
设计模式之 责任链模式
python·设计模式·责任链模式
古月居GYH1 小时前
在C++上实现反射用法
java·开发语言·c++
吾与谁归in1 小时前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式