Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 中断外部API调用的模式?_Java_Design Patterns - Fatal编程技术网

Java 中断外部API调用的模式?

Java 中断外部API调用的模式?,java,design-patterns,Java,Design Patterns,我正试着将我的思想集中在如何着手实现这个特定问题上。我们有一个执行某些逻辑并返回该逻辑结果的外部API。不幸的是,API返回一个新对象作为结果,而不仅仅是我感兴趣的部分。例如,代码如下所示: public class ComplexObject { //lots of fields } public interface LogicApplier { LogicResult applyLogic(ComplexObject obj); } public class LogicR

我正试着将我的思想集中在如何着手实现这个特定问题上。我们有一个执行某些逻辑并返回该逻辑结果的外部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的“权力”的最佳方式是什么?例如,我们首先调用逻辑的动机是派生一个缺少的字段,比如“name”。例如,在第二个实现中,该字段可能会有所不同,该实现现在希望从LogicApplierAPI派生“街道地址”。然而,没有什么可以阻止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;
    }

}

我认为您使用
有限实现逻辑应用程序的方法是正确的。您应该保护域中的对象免受外部可能的损坏。只更新您需要的字段


看起来您的
ComplexObject
是可变的。我会考虑把它隐藏在不可变的接口后面(没有任何设置或方法来改变被暴露的对象),并将不可变的接口传递到您的代码> LimeTimePrimLogLogic Apple:/Calp>中,因此它不可能改变<代码>复杂对象< /代码>。 如果您的API需要
ComplexObject
类型,并且您无法更改该类型,那么为了防止变异,您可以:

选择1


创建基本
ComplexObject
实例的
克隆
,并将其传递到API中。返回结果后,您将在未触及的
base
实例上更新所需字段。如果
ComplexObject
是“本身的东西”,并且其状态的更改不会在类实例之外产生副作用,例如更改数据库或影响其他状态,那么这将很好地工作

如果
ComplexObject
的突变有副作用,或者
将来可能有副作用,那么这是一个真正的问题

选择2

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


在我看来,这是有漏洞的,以后会产生更多的工作-如果
ComplexObject
稍后将使用新属性进行扩展,您将需要对
ReadonlyComplexObject
进行更改,否则仍然会发生变异。

ComplexObject
是一个可变的生成类,在整个代码库中使用,这使事情复杂化了。您的建议是让
LimitedImplementationLogicApplier
接受一个包装器,比如
ComplexObjectWrapperForImplementationOne
(更好的名称待定),哪种方法将我们的
ComplexObject
包装成只为我们期望变异的字段公开setter的东西?我更喜欢一个接口而不是
ComplexObject
(你能用该接口生成它吗?),但如果不可能,包装器也会工作。如果你能将一些不可变的东西传递到你的“派生”逻辑中,你将确保你的对象保持不变。不幸的是,它不能用接口生成。此外,“派生”逻辑在这里应被视为外部API,因此我们无法控制实现。它需要一个
ComplexObject
,并返回一个
ComplexObject
,这很可怕。因此,我认为最好的方法是围绕
ComplexObject
进行包装,只公开一些指定字段,围绕
logicalapplier
进行包装,以使用这个新的
ComplexObject
包装。这听起来对吗?更新了答案。我认为我的
选项2
最接近你的想法。我想你不可能有一个
ComplexObject
类型的包装器(这就是你的外部API想要的吧?),它的
字段/方法少于
ComplexObject
类型本身。我想我现在更倾向于选项1,感谢大家的集思广益。理由是:选项2需要构建一个新的包装器类来真正控制字段。。。这不是个坏主意,但可能是另一天的问题。看起来像是克隆对象,将其映射到指定的返回类型(
ImplOneResultObject
或类似的类型),然后将其全部隐藏在
logicalapplier
的包装器中。
LogicApplier
的API对客户端调用的更改很少,并且隐藏了克隆/转换等需要。再次感谢您的帮助。