Java 作为接口实现的抽象工厂模式

Java 作为接口实现的抽象工厂模式,java,design-patterns,interface,factory,Java,Design Patterns,Interface,Factory,我对抽象工厂模式很好奇。从Java8我们有默认方法,这是否意味着我们可以将抽象类替换为接口?我能看到的一个缺点是,当我们需要非静态/最终字段时。我们做不到。你能给我举几个例子(除了我列举的这一个)说明旧的时装工厂有更多的优势吗?从技术上讲,你可以,但你不应该 接口上的默认实现是一个具有一些非常特定用途的工具—主要用于向接口添加功能,该接口很可能是由您无法控制的客户机实现的,或者用于反复实现的接口,其中默认实现将很难重新实现 当您从一些常见父类的行为进行扩展时,它们并不打算作为抽象类的替换(甚至补

我对抽象工厂模式很好奇。从Java8我们有默认方法,这是否意味着我们可以将抽象类替换为接口?我能看到的一个缺点是,当我们需要非静态/最终字段时。我们做不到。你能给我举几个例子(除了我列举的这一个)说明旧的时装工厂有更多的优势吗?

从技术上讲,你可以,但你不应该

接口上的默认实现是一个具有一些非常特定用途的工具—主要用于向接口添加功能,该接口很可能是由您无法控制的客户机实现的,或者用于反复实现的接口,其中默认实现将很难重新实现

当您从一些常见父类的行为进行扩展时,它们并不打算作为抽象类的替换(甚至补充)

这就是说,抽象工厂模式与Java对抽象关键字的使用关系不大。抽象工厂模式是关于隐藏(或抽象)给定客户机实际用于生成对象的具体工厂实现。工厂的工厂方法定义为返回的可能是具体类、抽象类或接口

比如说-

假设你有课,Guipainer。它有一个方法#paintWindow

在封面下,您介绍了一个窗口,其中包含特定于操作系统的实现,如AppleWindow、AndroidWindow、UbunutuWindow(等等)。每个窗口实现的构造方式略有不同

一种方法是使用AppleWindowFactory、AndroidWindowFactory、UbuntuWindowFactory(等等)以及查找操作系统和决定使用哪个工厂的方法来构造GuiPainter。然而,Guipainer真正想要的只是Window的任何实例——它没有其他特定于操作系统的知识

因此,我们引入了WindowFactory,它返回一个窗口。WindowFactory是一个拥有发现操作系统和决定使用哪一个具体窗口工厂的知识的工厂,它将这种责任从Guipainer中抽象出来

窗口本身可能是一个具体的类,只有一个实现,只是基于操作系统的配置差异。它可能是一个抽象类,具有特定于操作系统的实现(如AppleWindow、AndroidWindow等)。它甚至可能是一个由工厂匿名实现的接口。窗口是什么并没有改变,客户端不再需要担心操作系统特定的废话来获得它想要的窗口


这有意义吗?

是的,这是一种广泛使用的技术

您经常会偶然发现公共
接口
,例如:

public interface Cache<K, V> {
    public Optional<V> get(K k);
    public V put(K k, V v);
    // ...
}
不需要有多个实现,即使只有一个子类,该模式也是有效且完全适用的


使用缓存系统的类不关心实现细节。他们只关心暴露的行为,这可以通过
界面
很好地描述

你说的是
default
factory
方法,但它们确实不同,我觉得你把事情搞混了

default
方法,因为如果您有20个类实现了
MyInterface
,并且您在接口中添加了一个方法,那么在20个不同的位置实现一个行为(通常在所有类中都是相同的)将是一项极其痛苦的工作

我觉得
java8/9+
正朝着这个模式发展:在
接口中使用工厂方法。以API
Set.of(…)
Map.of(…)
等为例

java.util.Stream
为例

您通常以这种方式使用它(对于对象):

您不关心当前拥有的元素是否是
元素、ref
元素或任何其他元素

这些是隐藏的细节,无法从代码中访问

然而,
接口
确实公开了
的工厂方法
(除其他外):


另请参见
java.util.Collection
及其子类。

的确如此,但我可以在使用接口而不是抽象类的情况下完成所有工作,问题是,为什么我不应该这样做?我可以用接口创建相同的抽象。“他们不是有意的”——为什么?TL;DR:在非常实际的术语中,带有默认实现的无状态类和接口通常是可互换的。也就是说,具有默认实现的接口允许您以无状态类不具备的方式(例如通过一个类实现两个具有相同方法定义的接口,但两者都提供默认实现)切割自己,并且仍然必须以匿名方式或作为工厂返回的任何内容的一部分进行实例化。你可以用螺丝刀把钉子钉进去,但用锤子更容易:)好吧,我现在看到了不同之处,谢谢你的链接和解释:)
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;
    // ...
}
private Stream<Element> stream;
private IntStream intStream;
/**
 * 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 class > other classes