根据条件创建不同的POJO子对象,但共享公共字段

时间:2018-02-14 06:56:57

标签: java design-patterns polymorphism

我正在实施日志管理系统,并希望日志类型可扩展。我们得到一个从JSON(来自Filebeat)解析的基础对象,例如:

class LogLine {
   String message
   Date timestamp
   String type
   String source
}

鉴于此LogLine对象,我希望能够创建不同的对象,这也将扩展此LogLine。

class SomeLog extends LogLine {
    int myfield
    String username
}

class SomeOtherLog extends LogLine {
   Date startTime
   Date endTime
   String username
   String transactionID
}

所以,在我目前的非理想实施中:

void parse(String s){
   LogLine logLine = .....parseFromString(s)
   if ( logline.type.equals('def') ){
      SomeLog someLog = new SomeLog.Builder.build(logLine)
   } else if ( logline.message.containts('abc') ){
      SomeOtherLog someotherLog = new SomeOtherLog.Builder.build(logline)
   }
}

但是,正如您可以想象的那样,子类中的构建器会复制超类LogLine对象,无论如何我可以在不复制值的情况下执行此操作,因为它们已经是子类了吗?是否有设计模式来实现这一目标?我不想依赖像BeanUtils.copyProperperties

这样的反思

2 个答案:

答案 0 :(得分:1)

当您基于另一个创建新对象时,最好制作一个所有字段的副本。这是一种名为defensive copying的最佳做法。

由于您解析了一个字符串,因此不需要防御性副本。此外,我想您要解析输入字符串中的某些特定字段,例如myfield的{​​{1}}和SomeLog的{​​{1}}。您可以重新设置对象创建,如

startDate

如果您有许多LogLine的子类,那么您可能希望将创建逻辑移动到SomeOtherLog,它管理有关将字符串解析为特定对象的所有内容。

答案 1 :(得分:1)

介绍用于创建LogLine个对象的工厂界面。

public interface LogLineFactory {
    public LogLine createLog(LogLine logLine);
}

并使用Map进行查找。

private Map<String, LogLineFactory > logLineFactories = new HashMap<>();

{
    logLineFactories .put("def", new SomeLogFactory());
    logLineFactories .put("abc", new SomeOtherLogFactory());
}

然后,您可以使用map looup忽略if else分支。

LogLine logLine = parseFromString(s);
LogFactory logFactory = logLineFactories.get(logLine.type);

if(logFactory != null) {
    LogLine wrappedLogLine = logFactory.createLog(logLine);
}

也许您需要更多信息来创建LogLine,并且您必须更改界面。

public interface LogLineFactory {
    public LogLine createLog(LogLine logLine, String s);
}

PS:使用Java 8,您可能希望使用方法引用。

logLineFactories.put("def", SomeLog::new);
logLineFactories.put("abc", SomeOtherLog::new);