作为接口实现的抽象工厂模式
Abstract Factory Pattern implemented as Interfaces
我对抽象工厂模式很好奇。从 Java 8 我们有默认方法,这是否意味着我们可以将我们的抽象 类 替换为接口?我可以看到的一个缺点是我们需要非静态/最终字段的情况。我们不能做接口。能举几个例子吗(除了我举的这一个)什么时候老式工厂更有优势?
技术上你可以,但你不应该。
接口上的默认实现是一种具有一些非常特定用途的工具 - 主要用于向接口添加功能,而该接口很可能已由您无法控制的客户端实现,或者用于已实现的接口重复,默认实现对 re-implement.
来说是繁重的
当您从一些常见的 parent 扩展时,它们 不是 作为抽象 class 的替代(甚至补充)行为。
也就是说,抽象工厂 pattern 与 Java 对 abstract 关键字的使用关系不大。抽象工厂模式是关于隐藏(或抽象掉)给定客户端实际用于生成 object 的具体工厂实现。工厂的工厂方法被定义为返回的可能是具体的class、抽象的class或接口
所以,例如-
假设您有一些 class,GuiPainter。它有一个方法,#paintWindow.
在幕后,您引入了 Window,具有 OS 特定实现,例如 AppleWindow、AndroidWindow、UbunutuWindow(等等)。每个 Window 实现在构建方式上都略有不同。
一种方法是使用 AppleWindowFactory、AndroidWindowFactory、UbuntuWindowFactory(等等)构建 GuiPainter,以及一种查找方法OS 并决定使用哪个工厂。然而,GuiPainter 真正想要的是 Window 的任何实例 - 它没有其他 OS-specific 知识。
因此,我们引入一个 Window 工厂,其中 returns 一个 Window。 WindowFactory 是一个具有发现 OS 和决定使用哪个具体 Window 工厂的知识的工厂 - 从 GuiPainter 中抽象出该责任。
Window 本身可能是一个具体的 class,具有单一的实现,只是基于 OS 的配置差异。它可能是具有 OS-specific 实现的抽象 class(如 AppleWindow、AndroidWindow 等)。它甚至可能是由工厂匿名实现的接口。 Window 是 并没有改变的是,客户不再需要担心 OS 特定的废话以获得它想要的 window。
这有意义吗?
是的,这是一种广泛使用的技术。
您经常会偶然发现 public interfaces
,例如:
public interface Cache<K, V> {
public Optional<V> get(K k);
public V put(K k, V v);
// ...
}
和隐藏(=package-private
或嵌套private
)实现。
class SoftCache<K, V> implements Cache<K, V> {
private final Map<K, SoftReference<V> dataMap;
// ...
}
class WeakCache<K, V> implements Cache<K, V> {
private final Map<K, WeakReference<V> dataMap;
// ...
}
不需要多个实现,即使只有一个,该模式也是有效且完全适用的sub-class。
您 类 使用缓存系统 不关心 实施细节。他们只关心暴露的行为,这可以通过 interface
.
很好地描述
您说的是 default
和 factory
方法,但它们确实彼此不同,我觉得您有点混淆了。
default
方法 were mostly added 因为如果你有 20 个 类 实现 MyInterface
并且你在你的接口中添加一个方法,这将是一个非常痛苦的工作在 20 个不同的地方实现一个行为(通常在所有 类 中都是相同的)。
我觉得 Java 8/9+
正在大力发展这种模式:interfaces
中的工厂方法。以 API Set.of(...)
、Map.of(...)
等为例。
以java.util.Stream<T>
为例
你通常这样使用它(对于对象):
private Stream<Element> stream;
或
private IntStream intStream;
您不关心当前拥有的元素是 Head
元素、OfRef
还是其他元素。
这些是隐藏的详细信息,您的代码无法访问。
然而,interface
Stream<T>
确实 公开了工厂方法 of
(以及其他):
/**
* Returns a sequential {@code Stream} containing a single element.
*
* @param t the single element
* @param <T> the type of stream elements
* @return a singleton sequential stream
*/
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
让你的 interface
公开工厂方法而不是 abstract
类 没有错,但归根结底,这完全取决于你和你的感受做事舒服。
还需要注意的是java
通常使用这种模式:
interface > abstract class > other classes
另请参阅 java.util.Collection<E>
及其 sub-classes。
我对抽象工厂模式很好奇。从 Java 8 我们有默认方法,这是否意味着我们可以将我们的抽象 类 替换为接口?我可以看到的一个缺点是我们需要非静态/最终字段的情况。我们不能做接口。能举几个例子吗(除了我举的这一个)什么时候老式工厂更有优势?
技术上你可以,但你不应该。
接口上的默认实现是一种具有一些非常特定用途的工具 - 主要用于向接口添加功能,而该接口很可能已由您无法控制的客户端实现,或者用于已实现的接口重复,默认实现对 re-implement.
来说是繁重的当您从一些常见的 parent 扩展时,它们 不是 作为抽象 class 的替代(甚至补充)行为。
也就是说,抽象工厂 pattern 与 Java 对 abstract 关键字的使用关系不大。抽象工厂模式是关于隐藏(或抽象掉)给定客户端实际用于生成 object 的具体工厂实现。工厂的工厂方法被定义为返回的可能是具体的class、抽象的class或接口
所以,例如-
假设您有一些 class,GuiPainter。它有一个方法,#paintWindow.
在幕后,您引入了 Window,具有 OS 特定实现,例如 AppleWindow、AndroidWindow、UbunutuWindow(等等)。每个 Window 实现在构建方式上都略有不同。
一种方法是使用 AppleWindowFactory、AndroidWindowFactory、UbuntuWindowFactory(等等)构建 GuiPainter,以及一种查找方法OS 并决定使用哪个工厂。然而,GuiPainter 真正想要的是 Window 的任何实例 - 它没有其他 OS-specific 知识。
因此,我们引入一个 Window 工厂,其中 returns 一个 Window。 WindowFactory 是一个具有发现 OS 和决定使用哪个具体 Window 工厂的知识的工厂 - 从 GuiPainter 中抽象出该责任。
Window 本身可能是一个具体的 class,具有单一的实现,只是基于 OS 的配置差异。它可能是具有 OS-specific 实现的抽象 class(如 AppleWindow、AndroidWindow 等)。它甚至可能是由工厂匿名实现的接口。 Window 是 并没有改变的是,客户不再需要担心 OS 特定的废话以获得它想要的 window。
这有意义吗?
是的,这是一种广泛使用的技术。
您经常会偶然发现 public interfaces
,例如:
public interface Cache<K, V> {
public Optional<V> get(K k);
public V put(K k, V v);
// ...
}
和隐藏(=package-private
或嵌套private
)实现。
class SoftCache<K, V> implements Cache<K, V> {
private final Map<K, SoftReference<V> dataMap;
// ...
}
class WeakCache<K, V> implements Cache<K, V> {
private final Map<K, WeakReference<V> dataMap;
// ...
}
不需要多个实现,即使只有一个,该模式也是有效且完全适用的sub-class。
您 类 使用缓存系统 不关心 实施细节。他们只关心暴露的行为,这可以通过 interface
.
您说的是 default
和 factory
方法,但它们确实彼此不同,我觉得您有点混淆了。
default
方法 were mostly added 因为如果你有 20 个 类 实现 MyInterface
并且你在你的接口中添加一个方法,这将是一个非常痛苦的工作在 20 个不同的地方实现一个行为(通常在所有 类 中都是相同的)。
我觉得 Java 8/9+
正在大力发展这种模式:interfaces
中的工厂方法。以 API Set.of(...)
、Map.of(...)
等为例。
以java.util.Stream<T>
为例
你通常这样使用它(对于对象):
private Stream<Element> stream;
或
private IntStream intStream;
您不关心当前拥有的元素是 Head
元素、OfRef
还是其他元素。
这些是隐藏的详细信息,您的代码无法访问。
然而,interface
Stream<T>
确实 公开了工厂方法 of
(以及其他):
/**
* Returns a sequential {@code Stream} containing a single element.
*
* @param t the single element
* @param <T> the type of stream elements
* @return a singleton sequential stream
*/
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
让你的 interface
公开工厂方法而不是 abstract
类 没有错,但归根结底,这完全取决于你和你的感受做事舒服。
还需要注意的是java
通常使用这种模式:
interface > abstract class > other classes
另请参阅 java.util.Collection<E>
及其 sub-classes。