首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >抽象工厂模式的接口实现

抽象工厂模式的接口实现
EN

Stack Overflow用户
提问于 2018-03-04 20:19:23
回答 2查看 650关注 0票数 1

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-05 13:57:35

你技术上可以,但你不应该。

接口上的默认实现是一个工具,它有一些非常具体的用途--主要用于向一个界面添加功能,该接口很可能是由您控制之外的客户端实现的,或者是一个已经多次实现的接口,在该接口中,默认实现将是很难重新实现的。

当您从某些常见的父级行为扩展时,它们并不打算作为抽象类的替代(甚至是补充)。

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

所以,例如-

假设您有一些类,GuiPainter。它有一个方法#油漆窗口。

在幕后,您已经介绍了一个窗口,它具有特定于操作系统的实现,比如AppleWindow、AndroidWindow、UbunutuWindow (等等)。每个窗口实现在所需的构造方式上略有不同。

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

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

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

这有意义吗?

票数 3
EN

Stack Overflow用户

发布于 2018-03-05 14:47:25

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

您经常会遇到公共interfaces,例如:

代码语言:javascript
运行
复制
public interface Cache<K, V> {
    public Optional<V> get(K k);
    public V put(K k, V v);
    // ...
}

隐藏(= package-private或嵌套private )实现。

代码语言:javascript
运行
复制
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

您正在谈论的是defaultfactory方法,但是它们确实不同,我觉得您正在混合一些东西。

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

我觉得Java 8/9+正在向这样的模式发展:interfaces中的工厂方法。以API Set.of(...)Map.of(...)等为例。

java.util.Stream<T>为例。

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

代码语言:javascript
运行
复制
private Stream<Element> stream;

代码语言:javascript
运行
复制
private IntStream intStream;

您不关心当前拥有的元素是Head元素、OfRef还是其他任何东西。

这些都是隐藏的细节,无法从您的代码中获得。

然而,interface Stream<T> does公开了工厂方法of (除其他外):

代码语言:javascript
运行
复制
/**
 * 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通常使用以下模式:

代码语言:javascript
运行
复制
interface > abstract class > other classes

还请参见java.util.Collection<E>及其子类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49099991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档