有效的 Java 由 Joshua Bloch:Item1 - 静态工厂方法

Posted

技术标签:

【中文标题】有效的 Java 由 Joshua Bloch:Item1 - 静态工厂方法【英文标题】:Effective Java By Joshua Bloch: Item1 - Static Factory Method 【发布时间】:2011-09-02 00:14:00 【问题描述】:

我正在阅读 Joshua Bloch 的 Effective Java,我对 Item1 Static Factory Method 有疑问。

引述[布洛赫,第 7 页]

接口不能有静态方法, 所以按照惯例,静态工厂 名为 Type 的接口的方法 放在不可实例化的类中 命名类型。例如,Java 集合框架,提供 不可修改的集合,同步 收藏品之类的。近乎全部 这些实现是出口 通过静态工厂方法合二为一 不可实例化的类 (java.util.Collections)。课程 返回的对象都是 非公开。

好的。查看源代码时,我看到 java.util.Collection 接口和 java.util.Collections 类与私有构造函数(非实例化类)。而且我看到不可实例化的类 Collections 具有所有静态方法,就像 Bloch 所说的那样。但我没有看到 Bloch 所说的两个类之间的联系

接口不能有静态方法,因此按照惯例,名为 Type 的接口的静态工厂方法放在名为 Types 的不可实例化类中。

    谁能指出对我来说显而易见的事情?

    他说的是什么意思

返回对象的类都是非公开的

这里是我获取 java 源的地方:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collection.java?av=f

【问题讨论】:

另见Bloch, Item 1。 任何关于 Bloch 的事情对我来说都是加一,默认情况下。 【参考方案1】:

以Collections.unmodifiableList(...) 为例。它返回 List 的一些实现。但是实现类的名称无关紧要。此外,该类通过静态工厂方法构造。

【讨论】:

【参考方案2】:

    接口不能有静态方法,因此按照惯例,名为 Type 的接口的静态工厂方法放在名为 Types 的不可实例化类中

    重点只是“Type[s]”上的复数's'。因此,如果您的接口被称为 Foo 并且您想要创建一些名为 MyFoo 的实现,那么您的工厂和实例化方法应该按照约定称为 Foos

    返回对象的类都是非公开的

    这意味着从工厂方法返回的对象类具有私有或默认可见性修饰符,如private class MyFoo 中那样,因此它们不能通过工厂方法以外的任何其他方式实例化。由于您无法使用私有内部的new 运算符构造对象,或者将私有类封装在其范围之外(反射除外)。

例如:

 public interface Foo //interface without plural 's' (question 1)
     public void bar();
 
 public abstract class Foos() // abstract factory with plural 's' (question 1)
    public static Foo createFoo()
        return new MyFoo();
    
    private class MyFoo implements Foo // a non visible implementation (question 2)
       public void bar()
    
 

【讨论】:

1 的精彩解释。我理解它必须更好。非常感谢。对于2:让返回对象成为私有类的实例有什么好处? 您可以在没有 API 用户注意的情况下切换实现,因为他自己从未使用 new 构造过其中一个对象。因此,如果您需要重新实现某些内容,您可以创建一个新版本而无需任何 API 更改 嗯,我发现我需要在内部类 MyFoo 中添加 'static' 修饰符才能使其编译...否则我会收到不存在 Foos 封闭实例的错误。我做错了吗? @Mats_SX:我刚刚读到了一些相关内容。 javarevisited.blogspot.sg/2012/02/… 它基本上归结为在内部 MyFoo 类中,您已经实例化了一个 Foos 的实例并引用它。 一个很好的例子是来自 Guava 的 Lists 类,它包含 List 实例的静态工厂函数。例如,您可以使用以下代码创建一个字符串列表:List<String> list = Lists.newArrayList("first", "second", "third")【参考方案3】:

1) 我不明白你的问题。 Collection 是接口,Collections 有一些工厂方法,例如 emptyList

2) 例如,Collection.emptyList 返回的 List 实例是实现 List 接口的私有类的实例。

【讨论】:

我还有一个问题要问你。对于2,让返回对象成为私有类的实例有什么好处?【参考方案4】:

它只是意味着Collections(和其他类似的类)中的静态工厂方法的返回类型是接口类型(例如List)而不是具体的实现类(例如java.util.Collections.UnmodifiableList),它们不是对用户可见,因为这只会使事情复杂化并增加 API 的大小。

【讨论】:

【参考方案5】:

假设您有一个名为List 的接口,并且您想使用静态工厂方法来创建不同类型的列表。您不能在List 接口中定义静态工厂方法,因为它是一个接口。所以你要做的就是有一个类,它返回实现 List 的类的实例

public class ListFactory
  private ListFactory()
  public static List makeArrayList()...
  public static List makeLinkedList()...
  public static List makeCrazyList()...

你不能这样做

public interface List
   public static List makeArrayList();
   public static List makeLinkedList();
   public static List makeCrazyList();

因为List 是接口。

【讨论】:

从 java 8 开始,接口不能包含静态方法的限制被取消了。【参考方案6】:
public interface Foo
    static public class Factory
        public Foo create()..

Foo foo = Foo.Factory.create();

【讨论】:

以上是关于有效的 Java 由 Joshua Bloch:Item1 - 静态工厂方法的主要内容,如果未能解决你的问题,请参考以下文章

Joshua Bloch 在 Effective Java 中解释的枚举类型

谁能解释一下 Joshua Bloch 第 41 条的例子? [复制]

Effective Java 3

如何在使用QuTiP绘制Bloch球体时给出aplot标题

了解 DAO 模式和接口

html 测试Joshua Canfield投资组合