什么是向这些库函数提供接口的最佳方法?

huangapple go评论69阅读模式
英文:

What's the best way to provide interface to these library functions?

问题

我正在构建一个库包,其中有一个名为 PropTransformer 的接口,将由30多个类实现。这里拿一个类来举例,比如 ShapeTransformer

public interface PropTransformer<T, R> {
    R transform(T t);
    T reverseTransform(R r);
}
public class ShapeTransformer implements PropTransformer<List<String>, Set<String>> {
    
    @Override
    public Set<String> transform(final List<String> list) {
        // 转换代码
    }

    @Override
    public List<String> reverseTransform(final Set<String> set) {
        // 反向转换代码
    }
}

这个库的类方法可以使用 new 运算符来调用,但由于用户可以在用户侧执行许多转换,因此会出现许多实例化。类似于:

new ShapeTransformer().transform(...); 
new TemperatureTransformer().transform(...);
...

我考虑过创建一个实用程序类 Transformer,它将为变换器提供直接调用,例如:

public class Transformer<T, R> {

    private static ShapeTransformer shapeTransformer = new ShapeTransformer();

    public static Set<String> shapeTransform(final List<String> list) {
        return shapeTransformer.transform(list);
    }

    public static List<String> shapeReverseTransform(final Set<String> set) {
        return shapeTransformer.reverseTransform(set);
    }
}

然后库用户可以这样使用它:

Transformer.shapeTransform(...)

这种方法的问题:

  • 随着实现 PropTransformer 的变换器数量增加,Transformer 类会不断增长,不易扩展。
  • Transformer 类中添加静态方法和变量会导致一些重复的工作。

有没有更清晰/更好的方法来实现这一点?通过方法引用和/或函数接口是否可行?

类似于:

Transformer t = new Transformer();
t.transform(ShapeTransformer::transform);
t.transform(TemperatureTransformer::transform);

(^ 这只是为了提供我期望的结果。我不一定建议使变换器方法静态)

英文:

I'm building a library package, which has an interface PropTransformer which will be implemented by 30+ classes. I'm taking one such class here say ShapeTransformer

public interface PropTransformer&lt;T, R&gt; {
    R transform(T t);
    T reverseTransform(R r);
}
public class ShapeTransformer implements PropTransformer&lt;List&lt;String&gt;, Set&lt;String&gt;&gt; {
    
    @Override
    public Set&lt;String&gt; transform(final List&lt;String&gt; list) {
        // transform code
    }

    @Override
    public List&lt;String&gt; reverseTransform(final Set&lt;String&gt; set) {
        // reverseTransform code
    }
}

This library's classes methods can be invoked using new operator obviously, but since a lot of transformations can be done on user side so a lot of instantiation will appear bloated. Something like:

new ShapeTransformer().transform(...); 
new TemperatureTransformer().transform(...);
...

I could think of creating a utility class Transformer which would provide a direct invocation for transformers, like

public class Transformer&lt;T, R&gt; {

    private static ShapeTransformer shapeTransformer = new CompatibleDevicesTransformer();

    public static Set&lt;String&gt; shapeTransform(final List&lt;String&gt; list) {
        return shapeTransformer.transform(list);
    }

    public static List&lt;String&gt; shapeReverseTransform(final Set&lt;String&gt; set) {
        return shapeTransformer.reverseTransform(set);
    }
}

Library user can then use it like

Transformer.shapeTransform(...)

Problems with this approach:

  • It won't scale as Transformer class will keep growing with number of transformers that implement PropTransformer.
  • Kind of repeat work is being done by adding static methods and variables in Transformer class

Is there a cleaner/better way to accomplish this? Through method reference(s) and/or functional interface(s), if possible?

Something like

Transformer t = new Transformer();
t.transform(ShapeTransformer::transform);
t.transform(TemperatureTransformer::transform);

(^ this is just to provide a peek into what I'm looking for. I'm not necessarily suggesting to make the transformers method static)

答案1

得分: 1

PropTransformer不是一个功能性接口,因为它包含不止一个抽象方法。因此,您不能使用lambda表达式来实现和调用这些方法。

您可以将PropTransformer拆分为功能性接口PropTransformerPropReverseTransformer。但决定应该基于PropTransformer如何适配整体设计。

为了进一步减少客户端代码中的样板代码,您可以创建PropTransformerFactory - 这是一个实用工具,用于创建PropTransformer的实现。
伪代码:

public class PropTransformerFactory {
    public static PropTransformer createShapeTransformer() {
        return new ShapeTransformer();
    }

    public static PropTransformer createTemperatureTransformer() {
        return new TemperatureTransformer();
    }
}
英文:

PropTransformer is not a functional interface as it contains more than 1 abstract method. So, you can't implement and call these methods using lamda expression.

You can split PropTransformer into functional interfaces PropTransformer and PropReverseTransformer. But decision should be based on how PropTransformer fit into overall design.

To further reduce boilerplate code at client side, you can create PropTransformerFactory - a utility to create PropTransformer implementations.
Pseudo Code:

public class PropTransformerFactory {
    public static PropTransformer createShapeTransformer() {
        return new ShapeTransformer();
    }

    public static PropTransformer createTemperatureTransformer() {
        return new TemperatureTransformer();
    }
}

huangapple
  • 本文由 发表于 2020年8月20日 14:50:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63499720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定