抽象工厂模式实现为接口
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了抽象工厂模式实现为接口相关的知识,希望对你有一定的参考价值。
我对抽象工厂模式很好奇。从Java 8我们有默认方法,它是否意味着我们可以将抽象类替换为接口?当我们需要非静态/最终字段时,我可以看到一个缺点。我们做不到界面。当老式工厂有更多的优势时,你能给我一些例子(除了我列出的那个)吗?
你在技术上可以,但你不应该。
接口上的默认实现是一个具有一些非常特定目的的工具 - 主要用于向控件之外的客户端实现非常可能实现的接口添加功能,或者用于重复实现的接口,默认情况下实施将是繁重的重新实施。
当您从一些普通父母的行为延伸时,它们不是用于抽象类的替代(或甚至补充)。
现在,也就是说,抽象工厂模式与Java使用abstract关键字几乎没有关系。抽象工厂模式是关于隐藏(或抽象)给定客户端实际用于生成对象的具体工厂实现。工厂的工厂方法定义为返回的内容可以是具体类,抽象类或接口。
所以,例如 -
假设你有一些班级,GuiPainter。它有一个方法#paintWindow。
在幕后,您已经介绍了一个Window,具有特定于操作系统的实现,如AppleWindow,androidWindow,UbunutuWindow(等)。每个Window实现在需要构建的方式上有所不同。
一种方法是使用AppleWindowFactory,AndroidWindowFactory,UbuntuWindowFactory(等)构建GuiPainter,以及找到操作系统并决定使用哪个工厂的方法。但是,所有GuiPainter真正想要的是Window的任何实例 - 它没有其他特定于操作系统的知识。
因此,我们引入一个WindowFactory,它返回一个Window。 WindowFactory是一个工厂,具有发现操作系统的知识,并决定使用哪个具体的Window工厂 - 从GuiPainter中抽象出这个责任。
窗口本身可能是具有单个实现的具体类,并且仅基于OS的配置差异。它可能是一个具有特定于操作系统的实现的抽象类(如AppleWindow,AndroidWindow等)。它甚至可能是由工厂匿名实现的接口。什么窗口不会改变,客户端不再需要担心操作系统特定的废话来获得它想要的窗口。
那有意义吗?
是的,这是一种广泛使用的技术。
你经常偶然发现公共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
方法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>
及其子类。
以上是关于抽象工厂模式实现为接口的主要内容,如果未能解决你的问题,请参考以下文章
设计模式抽象工厂模式 ( 简介 | 适用场景 | 优缺点 | 产品等级结构和产品族 | 代码示例 )