静态接口方法通用单例工厂之间的差异



在Effective Java Item 27中,Bloch提倡使用通用的单例工厂"创建一个不可变但适用于许多不同类型的对象"。 他的例子是:

interface UnaryFunction<T> {
    T apply(T t);
}
public class Example {
    private static UnaryFunction<Object> IDENTITY_FUNCTION = (k -> k);
    // [snip] detailed explanation of why this is safe...
    @SuppressWarnings("unchecked")
    public static <T> UnaryFunction<T> identityFunction() {
        return (UnaryFunction) IDENTITY_FUNCTION;
    }
    public static void main(String... args) {
        String[] strings = { "jute", "hemp", "nylon" };
        UnaryFunction<String> sameString = identityFunction();
        for (String s : strings) {
            System.out.println(sameString.apply(s));
        }
    }
}

以下是 OpenJDK 实现身份函数的方式:

@FunctionalInterface
interface UnaryOperator<T> extends Function<T, T> {
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

鉴于Java 8支持接口上的静态方法,通用单例工厂是否还有用例?

接口和泛型单例工厂中的默认方法彼此独立。

虽然通用单例工厂是一种实现技术,它允许您通过应用我们对 Java 内部的知识(特别是我们的类型擦除知识)在不同的上下文中重用相同的对象,但接口中的默认方法可以让您"水平"共享实现。

您可以通过在默认方法实现中使用通用单例工厂来组合这两种技术:

@FunctionalInterface
interface UnaryOperator<T> extends Function<T, T> {
    static UnaryOperator<Object> IDENTITY_FUNCTION = (k -> k);
    static <T> UnaryOperator<T> identity() {
        return (UnaryOperator)IDENTITY_FUNCTION;
    }
}

演示。

所以你的问题的答案是"不,静态接口方法不能取代通用的单例工厂"。

鉴于Java 8支持接口上的静态方法,通用单例工厂是否还有用例?

您提供的UnaryOperator示例不能保证提供单一实例。 允许但不是必需的这样做。

此外,如果您提供的代码确实提供了单例,那么它只是作为静态接口方法的通用单例工厂模式的实现。 然后它可能被证明是一个特别方便的实现,但它不是一个不同的替代本机。

即使您认为静态接口方法是一种不同的替代方案,它仍然只涵盖接口作者或维护者想到的情况。 如果你想要一个不同的,那么使用通用单例工厂的传统形式仍然是有意义的,比如:

public class Example {
    private final static UnaryFunction<Object> LOG_FUNCTION =
            (k -> { System.out.println(k); return k; });
    @SuppressWarnings("unchecked")
    public static <T> UnaryFunction<T> logFunction() {
        return (UnaryFunction) LOG_FUNCTION;
    }
    public static void main(String... args) {
        String[] strings = { "jute", "hemp", "nylon" };
        UnaryFunction<String> logIt = logFunction();
        for (String s : strings) {
            logIt(s);
        }
    }
}

相关内容

最新更新