用于中断外部API调用的模式吗?

时间:2019-06-11 01:58:37

标签: java design-patterns

我正在设法将精力集中在如何解决这个特定问题上。我们有一个执行某些逻辑并返回该逻辑结果的外部API。不幸的是,API返回的是一个新对象,而不是我感兴趣的部分。例如,代码看起来像这样:

public class ComplexObject {
    //lots of fields
}

public interface LogicApplier {
    LogicResult applyLogic(ComplexObject obj);
}

public class LogicResult {
    ComplexObject result;

    public ComplexObject getResult();
}

public class FirstImplementation {

    private LogicApplier _applier;

    public Implementation(LogicApplier applier) {
        _applier = applier;
    }

    public ComplexObject mainImplementation (ComplexObject apply) {
        LogicResult logicResult = _applier.applyLogic(apply);

        ComplexObject newComplexObject = logicResult.getResult();

        //Do some other stuff with new ComplexObject
    }
}

所以问题是:限制LogicApplier对FirstImplementation的“权力”的最佳方法是什么?例如,我们首先调用逻辑的动机是得出一个缺失的字段,比方说“名称”。例如,该字段可能在SecondImplementation中有所不同,该实现现在正在寻求从LogicApplier API派生“街道地址”。但是,没有什么可以阻止LogicApplier更改其他字段,例如“ idNumber”。

通过为我们的特定实现添加接口并手动映射字段来最好地解决此问题?像这样:

public interface SecondImplementationLogicApplier {

    public String deriveAddress(ComplexObject o);
}

public class LimitedImplementationLogicApplier implements FirstImplementationLogicApplier, SecondImplementationLogicApplier {
    LogicApplier _applier;
    public LimitedImplementationLogicApplier(LogicApplier applier) {
        _applier = applier;
    }

    public String deriveFirstName(ComplexObject o) {
     LogicResult res = _applier.applyLogic(o);
     return res.firstName;
    }


    public String deriveFirstName(ComplexObject o) {
     LogicResult res = _applier.applyLogic(o);
     return res.address;
    }

}

1 个答案:

答案 0 :(得分:1)

我认为您的LimitedImplementationLogicApplier步入正轨。您应该保护域中的对象免受外界可能的破坏。仅更新您需要的字段。

您的ComplexObject似乎是可变的。我会考虑将其隐藏在不可变的接口(没有任何设置方法或方法来更改暴露的对象)的后面,并将不可变的接口传递到您的LimitedImplementationLogicApplier中,因此它没有机会使ComplexObject发生变化。

如果您的API要求使用ComplexObject类型,并且您无法更改它,以防止发生突变,您可以:

选项1

在基础clone实例中创建一个ComplexObject,并将其传递到API。返回结果后,可以在未修改的base实例上更新必填字段。如果ComplexObject是“本身的东西”,并且其状态的更改在类实例之外没有副作用,例如更改数据库或影响其他状态,这将很好地工作。

如果ComplexObject的突变具有副作用或may have them in future,那么这确实是一个麻烦。

选项2

ReadonlyComplexObject继承一个ComplexObject类,并将其传递给API。在ReadonlyComplexObject中,您将抑制父级的所有行为以防止修改。

我认为这是很棘手的,以后会做更多的工作-如果以后用新属性扩展ComplexObject,则需要对ReadonlyComplexObject进行更改,否则仍然会发生变异。