【问题标题】:Design pattern to store data from different sources in one object将来自不同来源的数据存储在一个对象中的设计模式
【发布时间】:2019-03-12 12:26:38
【问题描述】:

我正在开发一个区块链(hyperledger indy)项目,以在链中存储关于成绩单等的可验证声明 (more detail)。 我有不同的学生数据提供者,他们都使用自己的格式来提供给我的数据。 我个人考虑过某种适配器模式,但想听听关于这种情况的其他意见。在下面的示例中,我试图让情况变得清晰,并展示例如两种不同的格式。

目标是将这些响应存储到一个对象中,以便能够将其保存在链中

{
  "student": "xxx",
  "grades": {
    "english": 9,
  }
}


<students>
    <student>
        <name>
        xxx
    </name>
        <age>
        17
    </age>
    </student>
</students>

【问题讨论】:

    标签: design-patterns format adapter blockchain


    【解决方案1】:

    一个选项是创建一个类,该类根据数据格式选择适当的解析器。例如,假设学生数据可以出现两种格式:(1) JSON 和 (2) XML:

    public class Student {
        // ...
    }
    
    public interface StudentParser {
        public Student parse(String data);
    }
    
    public class JsonStudentParser {
    
        @Override
        public Student parse(String data) {
            // ...
        }
    }
    
    public class XmlStudentParser {
    
        @Override
        public Student parse(String data) {
            // ...
        }
    }
    
    public class StudentDeserializer {
    
        private final StudentParser jsonParser = new JsonStudentParser();
        private final StudentParser xmlParser = new XmlStudentParser();
    
        public Student deserialize(String data) {
    
            if (isJson(data)) {
                return jsonParser.parse(data);
            }
            else if (isXml(data)) {
                return xmlParser.parse(data);
            }
            else {
                throw new UnknownStudentFormatException();
            }
        }
    }
    
    public class UnknownStudentFormatException extends RuntimeException {
        // ...
    }
    

    我已将区分 JSON 和 XML 数据的决定留给您,但结构是上述内容的重要部分。对于系统中可用的每种格式,都有一个StudentParser,并根据发现的格式选择正确的StudentParser。我不确定这种模式是否有正式名称,但我之前听说过它被称为Switchboard


    更高级

    如果您希望 StudentDeserializer 更通用(不仅依赖于 JSON 和 XML),您可以将决定 StudentParser 实现可以处理哪种格式的逻辑从 StudentDeserializer 移到实现本身。然后,StudentDeserializer 可以包含StudentParser 对象的列表,这些对象已注册,并选择一个可用于解析数据的对象。例如(StudentUnknownStudentFormatException与上例相同,已省略):

    public interface StudentParser {
        public Student parse(String data);
        public boolean canHandle(String data);
    }
    
    public class JsonStudentParser {
    
        @Override
        public Student parse(String data) {
            // ...
        }
    
        @Override
        public boolean canHandle(String data) {
            // ... is JSON? ...
        }
    }
    
    public class XmlStudentParser {
    
        @Override
        public Student parse(String data) {
            // ...
        }
    
        @Override
        public boolean canHandle(String data) {
            // ... is XML? ...
        }
    }
    
    public class StudentDeserializer {
    
        private final List<StudentParser> parsers = new ArrayList<>();
    
        public void registerParser(StudentParser parser) {
            parsers.add(parser);
        }
    
        public Student deserialize(String data) {
    
            return parsers.stream()
                .filter(parser -> parser.canHandle(data))
                .findFirst()
                .orElseThrow(() -> new UnknownStudentFormatException())
                .parse(data);
        }
    }
    

    然后可以注册StudentParser 实现:

    JsonStudentParser jsonParser = new JsonStudentParser();
    XmlStudentParser xmlParser = new XmlStudentParser();
    
    StudentDeserializer deserializer = new StudentDeserializer();
    deserializer.registerParser(jsonParser);
    deserializer.registerParser(xmlParser);
    
    deserializer.deserialize(someData);
    

    如果您有某种依赖注入 (DI) 框架,则可以自动装配 StudentParser 实现而不是手动注册它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多