有效的 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 中解释的枚举类型