java—对于具有不同输入参数和不同返回类型的多个实现的公共方法,应该使用什么设计模式?

jljoyd4f  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(578)

我是设计模式的新手,因此对所有可用模式的了解都很有限。我正在尝试为一个问题实现一个解决方案,并请求用户社区对使用什么设计模式以及应该如何实现提供一些指导。
任务:实现中央Map工厂,它接受一些输入x并将其转换为一些输出y。将来可以添加新的实现。
每个实现的输入参数都不同
每个实现的输出参数类型不同
到目前为止,我已经实施了工厂模式,但我对以下几点表示怀疑:
mapperfactory原始使用参数化类mappingutil时出现警告
在服务类中,当我使用factory mapperfactory.getmappingutils(“a”).mapdata(a)时,我必须强制转换输出,因为每个实现都有自己特定的outputformat(这是一种不好的做法吗)
这是解决问题的正确方法还是我在实现中遵循了任何反模式

public interface MappingUtil<X, Y> {
    Y mapData (X value);
}

@Component
public class A implements MappingUtil<Input A, OutputA> {

    @Override
    public OutputA mapData(Input A){
    // Perform some logic and convert InputA to OutputA and return Output A object
    }
   }

@Component
public class B implements MappingUtil<Input B, OutputB> {

    @Override
    public OutputB mapData(Input B){
    // Perform some logic and convert InputB to OutputB and return OutputB object
    }
   }

@Component
public class C implements MappingUtil<Input C, OutputC> {

    @Override
    public OutputC mapData(Input C){
    // Perform some logic and convert InputC to OutputC and return OutputC object
    }
   }
}

工厂级

@Component
public class MapperFactory {

private final static Logger LOGGER = LoggerFactory.getLogger(MapperFactory.class);
private static Map<String, MappingUtil> mapperStrategyMapping;

private final A a;
private final B b;
private final C c;

@PostConstruct
void init() {
    mapperStrategyMapping = new HashMap<>();
    mapperStrategyMapping.put("A", a);
    mapperStrategyMapping.put("B", b);
    mapperStrategyMapping.put("C", c);
}

@Autowired
MapperFactory(A a,
              B b,
              C c) {
    this.a = a;
    this.b = b;
    this.c = c;
}

public MappingUtil getMappingUtil(String mapperCode) throws Exception {
    if (mapperCode != null) {
        return mapperStrategyMapping.get(mapperCode);
    } else {
        LOGGER.error("Empty mapper code received");
        throw new Exception("Empty mapper code");
    }
}

工厂用途:

@Service
public class XyzImpl implements Xyz{

    private final MapperFactory mapperFactory;

    @Autowired
    XyzImpl(MapperFactory mapperFactory){
        this.mapperFactory = mapperFactory;
    } 

    public void doFunction1(Input a , Input b){
        OutputA outputA = (Output A) mapperFactory.getMappingUtils("A").mapData(a);
        OutputB outputB = (Output B) mapperFactory.getMappingUtils("B").mapData(b);
        // Perform some logic on Output A Output B
    }

    public void doFunction2(Input c){
        OutputC outputC = (Output C) mapperFactory.getMappingUtils("C").mapData(c);
        // Perform some logic on Output C
    }
}
rqenqsqc

rqenqsqc1#

我看不出有什么明显的问题,但我会继续找的。我最初的建议是:为什么不用 MappingUtil 你就是不用 java.util.Function (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/function/function.html). 这是一个功能接口,它正是您所需要的,得到一个类型的值 T 返回一个类型 R . 一个实现的代码如下所示:

@Component
public class A implements Function<InputA, OutputA> {

    @Override
    public OutputA apply(InputA input){
    // Perform some logic and convert InputA to OutputA and return Output A object
    }
}

在你的 MapperFactory 该字段将是:

private static Map<String, Function> mapperStrategyMapping;

你也可以简化你的工作 getMappingUtil 具体如下:

public Function getMappingUtil(String mapperCode) {
    return Optional.ofNullable(mapperCode)
        .map(mCode -> mapperStrategyMapping.get(mCode))
        .orElseThrow(() -> new IllegalArgumentException("Empty mapper code received"));
}

为了避免强制转换,我也不喜欢,因为我看不到很多选项,其中一个选项可以是为你的返回类型设置一个超类的边界 Function ,但也许这超出了你的练习范围。

相关问题