Design patterns 在一个对象中存储来自不同来源的数据的设计模式

Design patterns 在一个对象中存储来自不同来源的数据的设计模式,design-patterns,format,adapter,blockchain,Design Patterns,Format,Adapter,Blockchain,我正在一个区块链hyperledger indy项目中工作,以在链中存储关于成绩单等的可验证声明。 我有不同的学生数据提供者,他们都使用自己的数据格式,并将其传递给我。 我个人曾考虑过某种适配器模式,但我想听听关于这种情况的其他意见。在下面的例子中,我试图把情况弄清楚,并举例说明两种不同的格式 目标是将这些响应存储到一个对象中,以便能够将其保存在链中 { "student": "xxx", "grades": { "english": 9, } } <student

我正在一个区块链hyperledger indy项目中工作,以在链中存储关于成绩单等的可验证声明。 我有不同的学生数据提供者,他们都使用自己的数据格式,并将其传递给我。 我个人曾考虑过某种适配器模式,但我想听听关于这种情况的其他意见。在下面的例子中,我试图把情况弄清楚,并举例说明两种不同的格式

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

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


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

一个选项是创建一个类,该类根据数据的格式选择适当的解析器。例如,假设学生数据有两种显示格式: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。我不确定这样的模式是否有正式名称,但我以前听说它被称为交换机

更高级

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

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);
    }
}
如果您有某种依赖注入DI框架,那么可以在中自动连接StudentParser实现,而不是手动注册它们

JsonStudentParser jsonParser = new JsonStudentParser();
XmlStudentParser xmlParser = new XmlStudentParser();

StudentDeserializer deserializer = new StudentDeserializer();
deserializer.registerParser(jsonParser);
deserializer.registerParser(xmlParser);

deserializer.deserialize(someData);