簡體   English   中英

如何在沒有 switch case 的情況下從 json 列表實例化一組不同的對象?

[英]How to instantiate a set of different object from json list without switch case?

我想從 json 列表中實例化一組對象。

考慮json列表

[
   {
...
      "class":"object1",
      "area":45
...
   },
   {
...
      "class":"object2",
      "colour":"red"
   },
   {
...
      "class":"object3",
      "height":90
...
   }
]

肯定有定義每個對象的字段。 我為每個對象創建了一個記錄

public record object1 (String area, ...) {}

public record object2 (String colour, ...) {}

public record object3 (String height, ...) {}

一般來說,我可以創建一個 switch case 來檢查屬性類並選擇正確的記錄構造函數。 這在我看來是非常糟糕的風格。 過去,我使用了具有擬合超類的多態性。 並使用了創建對象的枚舉。 在這種情況下, record類只有超級對象。

我想堅持使用記錄,因為我只在這個對象中保存簡單的數據。

在那里我想知道如何處理這個問題。 處理此類事情的最佳做法是什么? 什么模式可以用來解決這個問題?

我將對我的評論進行一些擴展,以展示“元工廠”方法可能是什么樣子的粗略示例。

首先,為實際的對象工廠定義一個接口。 我將為您留下實現,這些實現非常簡單(就像您在 switch 塊中的情況一樣)。

interface Factory<T> { 
  //I'll assume you're using a JSON library here which provided a JsonObject class
  //Change the parameter as required to reflect your actual code
  T createInstance(JsonObject record);
}

然后創建一個存儲庫。 這也只是一個粗略的概述:

class FactoryRepo {
  //Mapping between name and type, this could also be maintained by the factories or some other piece of code
  Map<String, Class<?>> typeMapping = ...;

  //The actual repository, a simple map for starters
  Map<Class<?>, Factory<?>> repository = ...;

  //register a new factory, I'll add the name mapping too but you could move this into a separate method
  public <T> void registerFactory(String name, Class<T> type, Factory<T> factory) {
    typeMapping.put(name, type);
    repository.put(type, factory);
  }

  //lookup factory by class
  @SuppressWarnings({ "unchecked" })
  public <T> Factory<T> lookupFactory(Class<T> type) {
    //unfortunately this cast is necessary
    return (Factory<T>)repository.get(type);
  }
      
  //lookup factory by name
  public Factory<?> lookupFactory(String name) {
    return lookupFactory(typeMapping.get(name));
  }
}

當然,您需要注冊工廠。 這可以手動完成,也可以使用檢測實現的框架(例如 Spring、CDI 甚至 Java 的 SPI)來完成。 手動方法可能如下所示:

 FactoryRepo repo = ...; //get if from somewhere

 repo.registerFactory("object1", Object1Type.class, new Object1Factory());
 repo.registerFactory("object2",ColoredObject.class, record -> {
   //code to build an instance of ColoredObject from record and return it
 });

最后,你使用它:

 FactoryRepo repo = ...; //get if from somewhere

 JsonObject record = ...; //assumes you have it handy

 //Unfortunately, you only get "Object" since the record's class can be anything
 //If you have an interfacy etc. you could limit the boundary to this
 Factory<?> factory = repo.lookupFactory(record.get("class"));
 Object instance = factory.createInstance(record);


 //If you know the type, you can try like this:
 ColoredObject co = repo.lookupFactory(ColoredObject.class).createInstance(record);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM