我已经开始阅读Joshua Bloch" Effective Java" (第二版)。在阅读第2项(在面对许多构造函数参数时考虑构建器)时,有一个特定的声明,即作者使用 Class.newInstance()方法。具体来说,作者说
Java中的传统抽象工厂实现一直是" Class"对象,使用" newInstance"播放" build"方法
这部分让我感到困惑 - 我对抽象工厂设计模式的理解是它用于代表工厂的工厂。在我看来, Class.newInstance()方法更多地依赖于"静态工厂方法"编码哲学(顺便提一下,是同一本书中的第1项)
想法,有人吗?我一直在努力克服一些艰难的采访,如果我的基本面在出现进行此类采访之前是基本的话,我会非常感激。
感谢。
答案 0 :(得分:5)
这是我的意见。
首先,抽象工厂模式不是工厂的工厂。这种模式的关键方面是存在一个可访问的接口,该接口具有底层(可能无法访问)的工厂实现,通过该实现,您可以获得(可能无法访问)对象实现的可访问接口。我知道,在Gamma的书中我是如何理解这种模式的一些适用性条件的长篇讨厌的文字游戏:
- 系统应独立于其产品的创建,组合和表示方式
- 你想提供一个产品类库,你想要只显示它们的接口,而不是它们的实现。
最后你得到的是物品,而不是工厂。
其次,我不会在模式概念和语言关键字之间建立1:1的关系。 “抽象工厂”不一定总是转换为Java abstract class
或interface
构造。只要您以某种方式保证客户端代码独立于底层工厂和对象实现,您仍然可以拥有一个表示“抽象工厂”的常规,可扩展,可实例化的类。这是java.lang.Class
的情况,它不是抽象的,也不是接口,而是通过newInstance()
方法隐藏它所代表的类型的无参数构造函数实现。如果您使用它可能会更清楚:
Object o = Class.forName(type).newInstance();
Class
播放“抽象工厂”,Object
播放“抽象产品”到类型实现。
最后,newInstance()
不是静态工厂方法,我认为因为此模式旨在返回其实现的类的实例。 newInstance()
不会返回Class
或子Class
es的实例。它返回它所代表的类型的实例。正如布洛赫在他的书中所述,它既不是“工厂方法”。
答案 1 :(得分:3)
我认为抽象工厂不是“工厂工厂”。 AbstractFactory<T>
不会创建创建T
的工厂,而是直接创建T
。
它的抽象概念是允许逻辑创建T
来注入。例如,您可以:
public interface ConnectionFactory {
Connection newConnection();
}
//passed to your object normally:
public class RealConnectionFactory implements ConnectionFactory {
//...
}
//passed to your object when unit testing:
public class FakeConnectionFactory implements ConnectionFactory {
//...
}
//...
public class MyDao {
public MyDao(ConnectionFactory connectionFactory) {
this.conn = connectionFactory.newConnection();
}
}
在这种情况下,ConnectionFactory
会创建Connection
,但它是抽象的,因为它是一个接口。
我倾向于同意你的观点,Class<?>.newInstance()
不是抽象工厂的典型示例,因为Class
不是抽象,并且实际上无法扩展。您不能要求Class<Integer>
并让一个实现将新值初始化为1
,另一个将新值初始化为7
。
然而,您可以通过说Class<? extends InputStream>
之类的内容来展示InputStream
的抽象工厂,具体实现Class<SocketInputStream>
和Class<FileInputStream>
。这不是“抽象”的传统含义(仍然只有一个类:Class
)。
但即便如此,它作为一个抽象工厂也没用,因为你实现“工厂”的新具体版本的方式是创建一个扩展InputStream
的新类。这几乎不是抽象工厂的目的。
答案 2 :(得分:1)
在我看来,他指的是如下代码:
Integer.class.newInstance();
Class<T>
是抽象工厂。传递类型参数时,它变得具体,例如, Integer
。然后,您调用了“构建器”,newInstance()
。