java这样的OOP语言如何封装辅助函数(常用的api)?

use*_*729 3 java oop

这些功能可能很难适应特定的类,

处理它们的最佳做法是什么?

Esk*_*sko 5

我想你的意思是方法而不是函数?你真的应该想象这个词static在 Java 世界中不存在static,从长远来看,真的没有任何实际对你有好处的情况。

我实际上目前面临着类似的问题,我有一大堆 API 方法我想提供给用户使用,但我想隐藏下面的实际方法以隐藏实现细节。

问题当然是,如果我只是把所有东西都塞进一个类中,即使使用最好的自动完成工具,它也会变得庞大而难以使用。您最有可能真正遇到的问题不在于将这些方法放在哪里,而在于如何将它们呈现给用户。

为了解决这个我建议你创造一个通过调用访问您的辅助方法,对象的层次结构myUtil.someGroup().someMethod(param1, param2);这实际上是一些API如何:已经作品,例如流行的Web框架的Apache Wicket的是通过使用配置设置,它使用对象组成,允许本身具有多组不同的特征。

为了从理论真正充实到一个工作示例,让我们假设您有一堆图像处理方法,它们要么转换图像的尺寸,要么改变其属性,如颜色、亮度和对比度。而不是有这个:

public class ImageUtil {

    public static BufferedImage adjustHue(float difference,
                                          BufferedImage original) {
        /* ... */
        return adjusted;
    }

    public static BufferedImage adjustBrightness(float difference,
                                                 BufferedImage original) {
        /* ... */
        return adjusted;
    }

    public static BufferedImage adjustContrast(float difference,
                                               BufferedImage original) {
        /* ... */
        return adjusted;
    }

    public static BufferedImage setHeight(int newHeight,
                                          BufferedImage original) {
        /* ... */
        return adjusted;
    }

    public static BufferedImage setWidth(int newWidth,
                                         BufferedImage original) {
        /* ... */
        return adjusted;
    }

}
Run Code Online (Sandbox Code Playgroud)

您应该使用这些接口来描述每组操作:

public interface IImageColorOperations {

    BufferedImage adjustHue(float difference, BufferedImage original);

    BufferedImage adjustBrightness(float difference, BufferedImage original;)

    BufferedImage adjustContrast(float difference, BufferedImage original);

}

public interface IImageDimensionOperations {

    BufferedImage setHeight(int newHeight, BufferedImage original);

    BufferedImage setWidth(int newWidth, BufferedImage original);

}
Run Code Online (Sandbox Code Playgroud)

以及您在“主”图像实用程序类中实例化的每个接口的附带单独类,如下所示:

public class ImageUtils {

    private final IImageDimensionOperations dimension;
    private final IImageColorOperations color;

    public ImageUtils() {
        this(new ImageDimensionOperations(),
             new ImageColorOperations());
    }

    /**
     * Parameterized constructor which supports dependency injection, very handy
     * way to ensure that class always has the required accompanying classes and
     * this is easy to mock too for unit tests.
     */
    public ImageUtils(IImageDimensionOperations dimension,
                      IImageColorOperations color) {
        this.dimension = dimension;
        this.color = color;
    }

    /* utility methods go here */

}
Run Code Online (Sandbox Code Playgroud)

但是等等,这还不是全部!现在有两条路要走,您可以自己决定要走哪条路。

首先,您可以使用组合直接公开接口方法:

public class ImageUtils implements IImageDimensionOperations,
                                   IImageColorOperations {

    private final IImageDimensionOperations dimension;
    private final IImageColorOperations color;

    public ImageUtils() {
        this(new ImageDimensionOperations(),
             new ImageColorOperations());
    }
    /* etc. */
}
Run Code Online (Sandbox Code Playgroud)

有了这个,您只需要将对各种方法的调用委托给实际的操作类。这样做的缺点是,如果添加另一个方法,则必须同时修改此实用程序类和底层实现类。

您的第二个选择是直接公开操作类本身(这就是我在finals那里添加的原因!):

public class ImageUtils {

    public final IImageDimensionOperations dimension;
    public final IImageColorOperations color;

    public ImageUtils() {
        this(new ImageDimensionOperations(),
             new ImageColorOperations());
    }    

    public ImageUtils(IImageDimensionOperations dimension,
              IImageColorOperations color) {
        this.dimension = dimension;
        this.color = color;
    }

    /* Nothing else needed in this class, ever! */

}
Run Code Online (Sandbox Code Playgroud)

通过这样做,你会得到那些好看的电话,比如

BufferedImage adjusted = imageUtils.color.adjustHue(3.2f, original);
Run Code Online (Sandbox Code Playgroud)

并且当您向任一接口添加一些方法时,您的图像实用程序类中已经可以使用它们,而无需进行任何额外修改。是的,通常公共字段在 Java 中是一个很大的禁忌,但是我确实认为在这种情况下这并不是一件坏事,尤其是finals将字段标记为不可修改(至少在理论上如此)。