静态接口方法通用单件工厂的区别?

时间:2016-01-28 20:57:09

标签: java generics java-8

在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支持接口上的静态方法,是否还有通用单例工厂的用例?

2 个答案:

答案 0 :(得分:3)

接口和通用单件工厂中的默认方法是相互独立的。

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

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

public class TheMage extends JFrame {
      private static Player Ship = new Player(50,50);
...
@Override
public void keyPressed(KeyEvent ke) {
    TheMage.Ship //blah blah blah       
}

Demo.

所以答案是你的问题&#34;不,静态接口方法不能取代通用的单件工厂&#34;。

答案 1 :(得分:1)

  

鉴于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);
        }
    }
}