在 Java 中创建不依赖 if-else 的工厂方法

2024-03-13

目前我有一个方法,它充当基于给定字符串的工厂。 例如:

public Animal createAnimal(String action)
{
    if (action.equals("Meow"))
    {
        return new Cat();
    }
    else if (action.equals("Woof"))
    {
        return new Dog();
    }

    ...
    etc.
}

我想要做的是当类列表增长时避免整个 if-else 问题。 我认为我需要有两种方法,一种将字符串注册到类,另一种根据操作的字符串返回类。

在 Java 中执行此操作的好方法是什么?


您所做的可能是最好的方法,直到可以使用字符串开关为止。 (2019年编辑:可以使用字符串开关 - 使用它。)

您可以创建工厂对象以及从字符串到这些对象的映射。但在当前的 Java 中,这确实有点冗长。

private interface AnimalFactory {
    Animal create();
}
private static final Map<String,AnimalFactory> factoryMap =
    Collections.unmodifiableMap(new HashMap<String,AnimalFactory>() {{
        put("Meow", new AnimalFactory() { public Animal create() { return new Cat(); }});
        put("Woof", new AnimalFactory() { public Animal create() { return new Dog(); }});
    }});

public Animal createAnimal(String action) {
    AnimalFactory factory = factoryMap.get(action);
    if (factory == null) {
        throw new EhException();
    }
    return factory.create();
}

在最初编写此答案时,针对 JDK7 的功能可能会使代码如下所示。事实证明,lambda 出现在 Java SE 8 中,并且据我所知,还没有映射文字的计划。 (2016年编辑)

private interface AnimalFactory {
    Animal create();
}
private static final Map<String,AnimalFactory> factoryMap = {
    "Meow" : { -> new Cat() },
    "Woof" : { -> new Dog() },
};

public Animal createAnimal(String action) {
    AnimalFactory factory = factoryMap.get(action);
    if (factory == null) {
        throw EhException();
    }
    return factory.create();
}

2019年编辑:目前,这看起来像这样。

import java.util.function.*;
import static java.util.Map.entry;

private static final Map<String,Supplier<Animal>> factoryMap = Map.of(
    "Meow", Cat::new, // Alternatively: () -> new Cat()
    "Woof", Dog::new // Note: No extra comma like arrays.
);

// For more than 10, use Map.ofEntries and Map.entry.
private static final Map<String,Supplier<Animal>> factoryMap2 = Map.ofEntries(
    entry("Meow", Cat::new),
    ...
    entry("Woof", Dog::new) // Note: No extra comma.
);

public Animal createAnimal(String action) {
    Supplier<Animal> factory = factoryMap.get(action);
    if (factory == null) {
        throw EhException();
    }
    return factory.get();
}

如果要添加参数,则需要切换Supplier to Factory (and get变成apply这在上下文中也没有意义)。对于两个参数BiFunction。超过两个参数,您将再次尝试使其可读。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Java 中创建不依赖 if-else 的工厂方法 的相关文章

随机推荐

  • UTC 日期/时间字符串到时区

    如何将 UTC 日期 时间字符串 例如 2011 01 01 15 00 00 转换为 php 支持的任何给定时区 例如 America New York 或 Europe San Marino PHP s DateTime http ph
  • 如何在根据 XML 架构验证 XML 文件时获取错误的行号

    我正在尝试根据 W3C XML 架构验证 XML 以下代码完成该工作并在发生错误时报告 但我无法获取错误的行号 它总是返回 1 有没有简单的方法来获取行号 import java io File import javax xml XMLCo
  • Android 智能手机与其他设备之间的直接 Wifi 通信

    我想在 Android 设备和另一个设备 不是另一个 Android 智能手机 而是使用 C 实现的带 wifi 的设备 之间建立通信 通过 WIFI 我已经发现android提供了直接无线网络 http developer android
  • 获取两个表单以内联方式显示

    这不起作用
  • 在intellij中重新附加源?

    我希望调试到 jaxb impl 的源代码 我下载了版本 2 2 6 附加了源代码 然后意识到我正在调试的应用程序正在使用 jaxb impl 版本 2 2 3 现在我有了正确版本的源代码 2 2 3 我不知道如何从 2 2 6 源代码中删
  • 为什么 PHP 不使用 Internet Explorer 为特定用户保存会话变量?

    我的网站存在问题 其中 PHP 不为使用 Internet Explorer 的特定用户保存会话变量 但对于其他一些使用 Internet Explorer 的用户来说完全没有问题 使用其他浏览器的用户也没有任何问题 我创建了以下三个小脚本
  • 列表框,同步滚动

    我有两个列表框 大小相同 彼此相邻 基本上我用它们来表示链接的项目 类似于 Excel 中的 2 列和多行 其中一个是名字 另一个是姓氏 我想知道是否可以使一个列表框滚动时 另一个列表框与其同步滚动 希望这是有道理的 先谢谢了 None
  • EWS - 如何找到所有未完成的任务?

    我正在使用 Exchange Web 服务尝试获取所有未完成的 Outlook 任务的列表 我有一个 ExchangeService 实例 并尝试查找所有未完成的任务 如下所示 SearchFilter searchFilter new S
  • 数据流/apache beam 窗口中字节数的触发窗口

    我有一个简单的工作 将数据从 pub sub 移动到 gcs pub sub 主题是一个共享主题 具有许多不同大小的不同消息类型 我希望结果在 GCS 中相应地垂直分区 架构 版本 年 月 日 该父键下应该是当天的一组文件 并且文件的大小应
  • 加载后如何获取iframe主体?

    我需要在 iframe 加载后获取 iframe 主体 document getElementById frame contentDocument body假设 iframe 的 ID 是 将以纯 JavaScript 形式提供给您fram
  • 如何通过友好名称打开串口?

    友好名称 显示在 设备管理器 中 端口 COM 和 LPT 下的名称 编辑 下面提供了两个解决方案 一个使用 WMI 另一个使用 SetupAPI 贴出今晚的代码 供大家欣赏 public class SetupDiWrap static
  • 如何为两个Windows窗体应用程序共享一个IsolatedStorage?

    我在一个解决方案中有两个 Windows 窗体应用程序和库 Library类可以在IsolatedStorage中创建新的文件夹和文件 并列出IsolatedStorage中的所有文件和文件夹 第一个应用程序使用库类创建新文件夹 文件 我希
  • 如何在android中将UTC时间戳转换为设备本地时间

    我需要将从服务器获取的 UTC 时间戳转换为本地设备时间 目前 我的时间有 5 小时的差异 例如 当我发布到服务器时 发布时间显示为 5 小时前而不是一秒前 我该如何解决这个问题 下面是我所做的代码 long timestamp curso
  • 在 Spring Security 表单登录页面中获取原始请求 url

    我在我的 spring 安全配置文件中声明了以下内容 http www springframework org schema security spring security 2 0 1 xsd http www springframewo
  • 如何获取TextView的文字颜色?

    在给定的代码中 lbl 0 getTextColor 给出错误 但我不知道如何获取 java 文件中 textview 的文本颜色 请帮助我 public void angry View v if lbl 0 getTextColor Co
  • android中的权限请求代码

    请帮助我获取权限 WRITE EXTERNAL STORAGE 和 WRITE SETTINGS 的请求代码 另请让我知道请求代码的来源 一个简单的演示 Here thisActivity is the current activity i
  • Ember 数据 1.0.0:与每种类型的适配器和序列化器混淆

    我正在从 Ember 数据 0 13 迁移到 1 0 0 beta 根据文档https github com emberjs data blob master TRANSITION md https github com emberjs d
  • MS Access 插入不重复

    微软访问2003 表主 手机号文本 255 名字文本 255 姓氏文本 255 地址文本 255 表温度 手机编号文本 255 名字文本 255 姓氏文本 255 地址文本 255 主要有100条记录 临时有 30 条记录 两个表都有 10
  • 发送图像并使用 json 返回它?

    我试图使用 json 将图像发送到 php 中的 web 服务 但客户端 cnt 读取图像 当我把它还回来的时候
  • 在 Java 中创建不依赖 if-else 的工厂方法

    目前我有一个方法 它充当基于给定字符串的工厂 例如 public Animal createAnimal String action if action equals Meow return new Cat else if action e