我对抽象的工厂模式很好奇。在Java 8中,我们有默认方法,这是否意味着我们可以将抽象类替换为接口?我能看到的一个缺点是,当我们需要非静态/最终字段时。我们不能做接口。你能给我举几个例子(除了我列出的这个例子),旧时装工厂有更多的优势吗?
发布于 2018-03-05 05:57:35
你技术上可以,但你不应该。
接口上的默认实现是一个工具,它有一些非常具体的用途--主要用于向一个界面添加功能,该接口很可能是由您控制之外的客户端实现的,或者是一个已经多次实现的接口,在该接口中,默认实现将是很难重新实现的。
当您从某些常见的父级行为扩展时,它们并不打算作为抽象类的替代(甚至是补充)。
现在,这就是说,抽象工厂模式与Java使用抽象关键字没有什么关系。抽象工厂模式是隐藏(或抽象)给定客户端实际用于生成对象的具体工厂实现。工厂的工厂方法被定义为返回可能是一个具体的类、一个抽象类或一个接口。
所以,例如-
假设您有一些类,GuiPainter。它有一个方法#油漆窗口。
在幕后,您已经介绍了一个窗口,它具有特定于操作系统的实现,比如AppleWindow、AndroidWindow、UbunutuWindow (等等)。每个窗口实现在所需的构造方式上略有不同。
一种方法是使用一个AppleWindowFactory、一个AndroidWindowFactory、一个UbuntuWindowFactory (等等)来构造AppleWindowFactory,以及找到操作系统和决定使用哪个工厂的方法。然而,GuiPainter真正想要的只是窗口的任何实例--它没有其他特定于操作系统的知识。
因此,我们引入一个WindowFactory,它返回一个窗口。WindowFactory是一个工厂,它具有发现操作系统和决定使用哪些具体窗口工厂的知识--将该责任从GuiPainter中抽象出来。
窗口本身可能是一个具体的类,只有一个实现和基于OS的配置差异。它可能是一个具有特定于OS的实现的抽象类(如AppleWindow、AndroidWindow等)。它甚至可能是一个由工厂匿名实现的接口。什么窗口并没有改变,客户不再需要担心操作系统特定的胡说八道才能得到它想要的窗口。
这有意义吗?
发布于 2018-03-05 06:47:25
是的,这是一种广泛使用的技术。
您经常会遇到公共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;
// ...
}
不需要多个实现,即使只有一个子类,模式也是有效和完全适用的。
使用缓存系统的类不关心的实现细节。他们只关心暴露的行为,这是通过一个很好地描述的interface
。
您正在谈论的是default
和factory
方法,但是它们确实不同,我觉得您正在混合一些东西。
default
方法主要是添加,因为如果您有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>
does公开了工厂方法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>
及其子类。
https://stackoverflow.com/questions/49099991
复制