java - Java Map Object,以 map 表示的对象

标签 java

我正在考虑在Java中使用对象的不同表示形式,以提供更大的灵活性。我最大的需要是动态地通过系统传递数据,以便在系统中的某个时刻使用脚本引擎进行处理。

我的问题是仅将对象表示为Map<String, Object>是否不是一个好主意。例如,如果我要继续前进,我将来会为自己创建一些严重的问题吗?这样做本质上是一个坏主意,为什么?等等...

例如,我可以像这样实现它

public class Foo {
   private final Map<String, Object> data;

   public Foo ()
   {
      this.data = new HashMap(); 
   }

   public String getProperty1() { return this.data.get("property1"); }
   public int getProperty2() { return this.data.get("property2"); }
   public Object getDynamicData(String key) { return this.data.get(key); }

   //Use builder to set properties in data and create the Foo object...
}


在进行此操作时,我还有其他事情要做,例如使用名为FooFields的第二个对象,该对象保存已知属性和键的类型,以使事情更好地进行查找。但是总体上我已经看到了一些问题。


vs POJO无疑增加了复杂性
将对象过渡到UI层或DB层更加困难
尽管使用FooFields进行构建以给我进行编译时错误检查,但在某些情况下我仍然会遇到运行时错误


另一个解决方案可能是

public class Foo {
   private final String property1;
   private final int property2;
   private final Map<String, Object> dynamicData;

   public Foo (String property1, int property2, Map<String, Object> data)
   {
      this.property1 = property1;
      this.property2 = property2;
      this.dynamicData = data;
   }

   public String getProperty1() { return this.property1; }
   public int getProperty2() { return this.property2; }
   public Object getDynamicData(String key) 
   { 
       return this.dynamicData.get(key); 
   }
}

最佳答案

我最大的需要是在系统中的某个点上动态地通过系统传递数据以使用脚本引擎进行处理……我的问题是,单纯地将对象表示为Map<String, Object>是否不是一个坏主意,例如会继续前进吗,我将来会为自己创建一些严重的问题吗?这样做本质上是一个坏主意,为什么?


我认为这是对您的问题的一种完全合法的解决方法,对于许多信息处理问题而言,这比许多实际问题要多。将模型信息集映射为它们的信息集。


信息的意思是“具有意义的数据”(即使头脑具有“形式”)。具有有意义命名的键的单个值(在映射中)实际上是一条信息。
(开放)集是不同元素(例如键-值对)的集合,仅此而已。


首先,商务人士将信息集视为字面上的信息集-通常在电子表格,纸质表格或屏幕中。他们不认为它们是具有“行为”的活呼吸对象,应该以某种方式“与信息紧密地结合在一起”。 (如果您确实认为自己的业务公理或不变量覆盖了您认为值得在有状态对象中实现的信息项,请填充靴子,但是,将相同的不变性同样容易地应用于通过地图的无状态对象方法中,而且更容易命名。)

同样,为单个信息项(例如“ customerForename”或“ productId”或“ lineItemQuantity”)查找基于域名的长期有效名称要比为业务“实体”寻找长期存在的名称和合同要容易得多”。例如,假设您一开始就将信息集命名为“客户”,但是现在输入的信息集中既包含客户信息,也包含一些订单信息。您是否应该将信息分解为单独的“客户”和“订单”对象,以期有一天分离能获得回报。从理论上讲,Order具有LineItem对象的列表,但LineItems不应同时包含“ productId”和“ productTitle”以便在其他上下文中可重复使用,但是我的信息集没有“ productTitle”,因此也许它们应该是可选的吗?我该如何验证?等等等等。...现在,我的信息集分布在三个DTO(也许在不同的包装中),只是为了惯用地捕获此单个信息集。建模练习永远无法完全满足不断变化的需求,变得越来越耦合,并且变得越来越难维护-收益很少。

或者,您可以只将Customer和Orders信息填充到与以前仅用于Customer信息的地图相同的地图中-再次使用精心挑选的长期键名来指定地图中包含的新信息。他们在一起-为什么不把他们在一起。如果您需要将它们拆分为单独的地图,请执行此操作。映射(真正的集合)易于拆分,合并,增长和缩小,而不会对它们代表的内容产生精神分裂症-因为与POJO / DTO不同,它们不会对应该包含的内容做出艰难的选择,这会使代码难以生存使用它们。不再需要对信息集中的字段进行不间断的更改,而是尝试删除POJO构造函数的第三个参数,而不会在整个生产和测试代码中引起编译问题。

另外,如果要从一个信息集转换为另一信息集,请尝试在同一地图中累积转换后的数据。毕竟,您不是只是在旧信息的基础上添加新信息吗?如果以后需要分开可以。在过去,客户保留纸质申请表,并在其后附加任何内部信件/决定(带回形针),而不是替换它。这意味着可以在仅引用其关注的地图中数据的流水线中逐步应用处理规则,并且该地图会慢慢积累更多信息。这样就可以轻松地细分和添加(和测试)规则,而不必携带不必要的额外信息,也不会在信息集增长或收缩时无处不在打破合同。

它不是OO-但这并不是避免它的唯一原因。但是,它是许多其他语言(OO语言或其他语言)中的惯用方法。 Javascript的对象只是映射。 Groovy,Ruby和Python都看到了本机map / hash / dictionary类型结构的普遍使用。 Clojure自觉地将地图(列表和集合,具有统一的“ seq”抽象)包含为通过函数传递的所有信息的无处不在的集合,这是出于这些良好的原因以及其他原因。的确,所有这些都是动态语言,而谦虚的java.util.Map可能很难用于此类模式,因为通常需要进行类转换(除非您提前知道地图将始终包含的内容),并且没有optional ()等。更重要的是,您不能再简单地使用IDE自动完成功能来告诉您类中有哪些可用信息(赞!)。然而,回报是存在的。

这些要点中的大多数都是Clojure社区中精通的主题,但我希望Java社区中也有更多关于这些主题的讨论:)

关于java - Java Map Object,以 map 表示的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46472740/

相关文章:

java8从对象基本条件列表中删除对象

java - 拆分字符串(尤其是在 Java 中使用 java.util.regex 或其他东西)

java - 在 thymeleaf 中编写 Java 代码

java - 获取下拉列表中选项的值并在 if 语句中使用它

java - 如何部分更新/重新绘制 jpanel(背景内容不会再次绘制。它保持原样)

java - 如何将这种过程式编程转换为面向对象编程?

java - 从 PHP 向 Java 发送信息

java - 使用 Log4J 属性文件免除给定类不写入我的日志文件的义务

java - 使用 Java 发送 HTTP Post Payload

将私钥作为字符串的 Java SFTP 客户端