Java 重构建议:映射到POJO

Java 重构建议:映射到POJO,java,dictionary,architecture,refactoring,Java,Dictionary,Architecture,Refactoring,我目前是一个项目的一部分,该项目有如下界面: public interface RepositoryOperation { public OperationResult execute(Map<RepOpParam, Object> params); } 在所有具体操作之后,将定义(扩展)它们自己的OperationParam,并且所需的参数将对每个人可见。(这是IMHO做这种事情的“正常方式”) 因此,在我看来,由于接口实现者众多,我有几种选择: 尝试更改接口并重写

我目前是一个项目的一部分,该项目有如下界面:

public interface RepositoryOperation {

    public OperationResult execute(Map<RepOpParam, Object> params);  
}
在所有具体操作之后,将定义(扩展)它们自己的OperationParam,并且所需的参数将对每个人可见。(这是IMHO做这种事情的“正常方式”)

因此,在我看来,由于接口实现者众多,我有几种选择:

  • 尝试更改接口并重写所有操作调用,以使用对象而不是映射。这似乎是最干净的,但我认为,由于操作太多,在实践中可能会有太多的工作。(约2周,可能有测试)

  • 向接口添加一个附加方法,如下所示:

    public interface RepositoryOperation {
    
        public OperationResult execute(OperationParam param);  
    }
    
    public interface RepositoryOperation {
        public OperationResult execute(Map<String, Object> params);
        public OperationResult execute(OperationParam params);  
    }
    
    公共接口存储操作{
    公共操作结果执行(映射参数);
    公共操作结果执行(操作参数参数);
    }
    
    并在功能实现过程中,每当遇到map调用时修复它们

  • 接受它(请不要!)

  • 所以我的问题是

    有没有人看到更好的“修复”地图的方法?如果有,你会用方法1或2修复它们,还是根本不修复它们

    编辑: 谢谢你的回答。如果可以的话,我会接受Max和Riduidel的答案,但既然我不能接受,我就更倾向于Riduidel的答案。

    我可以看到第三种方法

    您有一张由
    组成的地图。如果我没弄错的话,困扰你的是没有类型检查。显然,这并不理想。但是,可以将类型检查问题从整个参数(您的
    OperationParam
    )移动到单个
    repoparam
    。让我解释一下

    假设您的
    RepOpParam
    接口(当前看起来像a)被修改为:

    public interface RepOpParam<Value> {
        public Value getValue(Map<RepOpParam, Object> parameters);
    }
    
    有新的要求

    String myName = ParamName.NAME1.getValue(params);
    
    明显的附带优势是,现在可以为参数设置一个默认值,隐藏在其定义中


    不过,我必须明确指出,第三种方法只不过是将第二种方法的两个操作合并为一个操作,尊重旧的代码原型,同时在其中添加新的功能。因此,我会亲自走第一步,用现代对象重写所有的“东西”(另外,考虑一下配置库,这可能会导致你对这个问题感兴趣)。

    < P>听起来你有一个不必要的和错误的抽象。每当我看到一个包含一个方法的接口时,我都会考虑策略模式或操作模式,这取决于您是否在运行时做出决策

    清理代码的一种方法是让每个RepositoryOperation实现都有一个构造函数,该构造函数接受正确运行execute方法所需的特定参数。这样,地图中的对象值就不会出现混乱的转换


    如果希望保留execute方法签名,可以使用泛型对映射的值进行更严格的限制。

    首先,我认为接口并不完美。您可以添加一些泛型,使其更美观:

    public interface RepositoryOperation<P extends OperationParam, R extends OperationResult> {
        public R execute(T params);  
    }
    
    public class DeleteOperation implements RepositoryOperation<DeleteParam, DeleteResult> {
        public DeleteResult execute(DeleteParam param) {
            database.delete(param.getID());
            ...
        }
    }
    
    公共接口存储操作{
    公共R执行(T参数);
    }
    
    现在,我们需要一些向后兼容的代码。我同意这一点:

    //We are using basic types for deprecated operations
    public abstract class DeprecatedRepositoryOperation implements RepositoryOperation<OperationParam, OperationResult> {
        //Each of our operations will need to implement this method
        public abstract OperationResult execute(Map<String, Object> params);
    
        //This will be the method that we can call from the outside
        public OperationResult execute(OperationParam params) {
            Map<String, Object> paramMap = getMapFromObj(params);
            return execute(paramMap);
        }
    }
    
    //我们正在对不推荐使用的操作使用基本类型
    公共抽象类DeprecatedRepositoryOperation实现RepositoryOperation{
    //我们的每个操作都需要实现此方法
    公共抽象操作结果执行(映射参数);
    //这将是我们可以从外部调用的方法
    公共操作结果执行(操作参数参数){
    Map paramMap=getMapFromObj(params);
    返回执行(paramMap);
    }
    }
    
    以下是旧操作的外观:

    public class SomeOldOperation extends DeprecatedRepositoryOperation {
        public OperationResult execute(Map<String, Object> params) {
            //Same old code as was here before. Nothing changes
        }
    }
    
    public类SomeOldOperation扩展了DeprecatedRepositoryOperation{
    公共操作结果执行(映射参数){
    //和以前的代码一样,没有任何变化
    }
    }
    
    新操作将更美观:

    public interface RepositoryOperation<P extends OperationParam, R extends OperationResult> {
        public R execute(T params);  
    }
    
    public class DeleteOperation implements RepositoryOperation<DeleteParam, DeleteResult> {
        public DeleteResult execute(DeleteParam param) {
            database.delete(param.getID());
            ...
        }
    }
    
    public类DeleteOperation实现RepositoryOperation{
    公共DeleteResult执行(DeleteParam-param){
    delete(param.getID());
    ...
    }
    }
    
    但是调用代码现在可以使用这两个函数(代码示例):

    String operationName=getOperationName()//=“删除”
    映射操作Map=getOperations()//=所有操作的列表
    OperationParam param=getParam()//=删除参数
    operationMap.execute(参数);
    
    如果该操作是旧操作,则将使用DeprecatedRepositoryOperation中的转换器方法。
    如果操作是新的,它将使用新的
    public R execute(T params)
    函数。

    非常感谢您的绝妙解决方案。我会让这个问题在我的脑海里“萦绕”几个小时:)这不是一种方法。我只发布了与问题相关的内容。我发布了一个非常“精简”的界面版本。我大体上同意你的建议,但这仍然无助于旧的运作。我需要一种快速使它们更漂亮的方法:)并且不要花2周的时间进行重构。新操作当然将使用“新方法”,不管是什么:)我提出的方法允许您简单地将所有旧操作扩展为DeprecatedRepositoryOperation,它们将被代理为“新”操作语法。但是,向其中提供参数的方式可能很复杂。但我不认为有什么方法可以加快这一部分的重构。如果您以映射形式接收参数,则需要将其转换为对象,或将其作为映射进一步传递。同意。。。我也开始认为可能根本就没有捷径。
    String operationName = getOperationName(); //="Delete"
    Map<String, RepositoryOperation> operationMap = getOperations(); //=List of all operations
    OperationParam param = getParam(); //=DeleteParam   
    operationMap.execute(param);