11

我已经开始阅读 Joshua Bloch 的“Effective Java”(第二版)。在阅读第 2 条时(在面对许多构造函数参数时考虑构建器),作者在Class.newInstance()方法中做了一个特殊的陈述。具体来说,作者说

Java 中的传统抽象工厂实现是“Class”对象,“newInstance”方法扮演“build”方法的一部分。

这部分让我有点困惑——我对抽象工厂设计模式的理解是它用于表示工厂的工厂。在我看来, Class.newInstance()方法更接近于“静态工厂方法”编码哲学(顺便说一下,这是同一本书中的第 1 项)

想法,有人吗?我一直在努力准备应对一些艰难的面试,如果我在参加此类面试之前基础扎实,我将不胜感激。

谢谢。

4

3 回答 3

6

这是我的意见。

首先,抽象工厂模式并非旨在成为工厂的工厂。这种模式的关键方面是有一个可访问的接口和一个底层的(可能不可访问的)工厂实现,通过它您可以获得(可能不可访问的)对象实现的可访问接口。我知道,对于我如何理解 Gamma 书中这种模式的一些适用条件,这是一个很长的讨厌的文字游戏:

  • 系统应该独立于其产品的创建、组合和表示方式
  • 您想提供一个产品类库,并且您只想显示它们的接口,而不是它们的实现。

最后你得到的是对象,而不是工厂。

其次,我不会在模式概念和语言关键字之间建立 1:1 的关系。“抽象工厂”不一定总是转换为 Javaabstract classinterface构造。只要您以某种方式保证客户端代码独立于底层工厂和对象实现,您仍然可以拥有一个表示“抽象工厂”的常规、可扩展、可实例化的类。就是这种情况java.lang.Class,它既不是抽象的也不是接口,而是隐藏了它通过newInstance()方法表示的类型的无参数构造函数实现。如果您像这样使用它可能会更清楚:

Object o = Class.forName(type).newInstance();

Class播放“抽象工厂”,并Object播放“抽象产品”到类型实现。

最后,newInstance()不是静态工厂方法,我认为是因为这种模式旨在返回实现它的类的实例。newInstance()不返回Classnor sub-的实例Class。它返回它所代表的类型的实例。正如布洛赫在他的书中所说的那样,它也不是一种“工厂方法”。

于 2012-09-04T21:48:24.757 回答
3

我不认为有任何迹象表明抽象工厂是“工厂的工厂”。AnAbstractFactory<T>不会创建创建Ts 的工厂,而是T直接创建 s。

它是抽象的想法是允许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创建Connections,但它是抽象的,因为它是一个接口。

我倾向于同意您的观点,这Class<?>.newInstance()不是抽象工厂的典型示例,因为它不是抽象的,实际上它无法扩展。您不能要求一个实现将新值初始化为,而另一个实现将新值初始化为。ClassClass<Integer>17

但是,您可以通过说Class<? extends InputStream>是 s 的抽象工厂InputStream,具有具体实现Class<SocketInputStream>Class<FileInputStream>. 不过,这不是“抽象”的传统含义(仍然只有一类:)Class

但即便如此,它作为抽象工厂也没有用,因为实现“工厂”的新具体版本的方式是创建一个扩展的新类InputStream。这几乎不是抽象工厂的用途。

于 2012-09-04T20:15:37.383 回答
1

在我看来,他指的是如下代码:

Integer.class.newInstance();

Class<T>抽象工厂在哪里。当您传递类型参数时,它变得具体,例如Integer. 然后,您调用了“生成器”,newInstance()

于 2012-09-04T19:47:07.823 回答