抽象:可选方法?[java](建模过滤器) 出身背景

抽象:可选方法?[java](建模过滤器) 出身背景,java,abstraction,Java,Abstraction,在我的作业中,我被要求对滤波器进行建模,例如在基本水平上对信号处理中的滤波器进行建模。过滤器可以接受任何类型的输入并输出不同的类型(如果过滤器是这样实现的)。最简单的过滤器输出输入。其他示例过滤器是算术平均值、最大值或最小值过滤器,它们返回最大输入。类似的过滤器只能返回最后N个输入的平均值/最大值/最小值。有些过滤器可以重置,并且有一个方法重置,该方法接受相同类型的输入。例如,max3过滤器返回最后三个输入的最大数量,或者自上次重置(包括重置方法接受的输入)以来的最大数量。这个任务更详细地描述了

在我的作业中,我被要求对滤波器进行建模,例如在基本水平上对信号处理中的滤波器进行建模。过滤器可以接受任何类型的输入并输出不同的类型(如果过滤器是这样实现的)。最简单的过滤器输出输入。其他示例过滤器是算术平均值、最大值或最小值过滤器,它们返回最大输入。类似的过滤器只能返回最后N个输入的平均值/最大值/最小值。有些过滤器可以重置,并且有一个方法重置,该方法接受相同类型的输入。例如,max3过滤器返回最后三个输入的最大数量,或者自上次重置(包括重置方法接受的输入)以来的最大数量。这个任务更详细地描述了其他更复杂的过滤器,但我在最基本的抽象层次上遇到了麻烦

企图 所以我的第一次尝试是创建一个接口过滤器,它有一个方法过滤器。这将由过滤器实现,以满足其自身需求。我创建了一个抽象类StorageFilter,它存储了一个可以通过受保护的set/get方法访问的输入列表。然后,我扩展了该类,以在另一个抽象类ResetableFilter中实现reset函数。因此,不能重置的过滤器将扩展第一个抽象过滤器,而可以重置第二个的过滤器。但我的实现并没有真正起作用,因为过滤器比这复杂一点。我可以确定几种主要类型的过滤器。过滤器包括:

存储一个输入,如最大/最小过滤器:只需将存储值与输入进行比较,如果是新的最大/最小值,则将存储值设置为输入。我们称之为1型。 存储输入列表,例如最后N个的max/min filters:仅存储最后N个输入,以便filter方法可以遍历列表并找到max/min。我们将此类型称为2。这也可以通过另一种方式实现,存储两个值,一个表示当前最大/最小值及其年龄 存储一个输入列表和一个输出列表,例如复杂的标量线性滤波器,它使用方程和方程计算新的输出。我们称之为3型。 完全不存储像第一个示例这样的简单过滤器或只返回两倍输入的过滤器。我们称之为4型 因此,过滤器可以存储多种类型的内容,但并非所有过滤器都可以重置

问题 我的一般问题是,如何在维护抽象的同时实现可选方法?此类型筛选器可以具有其子类型可以具有的可选方法重置。我不能让一个空的方法复位,它什么也不做,但是过滤器仍然能够调用。在维护抽象的同时实现可选方法的最佳方法是什么

潜在解决方案 Use@Optional:使用此注释意味着不使用此方法的筛选器将抛出UnsupportedOperationException。这是一种可以接受的维护抽象的方法,因为Java的集合使用它,但由于涉及异常,所以这是不可取的。 创建一个重置接口,并让每个可以重置的过滤器实现它:这也很糟糕,因为它几乎会使我不得不考虑的过滤器类型增加一倍。i、 e 1型过滤器、可复位1型过滤器、…、和4型过滤器。因为类型4过滤器不存储任何东西,所以它们永远不会重置 《代码完成2》一书描述了一个为猫建模的场景。猫可以抓,但有些猫被除法,因此不能抓。为一只猫能做或不能做的事情创建不同的类会使它变得复杂,所以你最终会得到一个像猫一样的类。这本书提供的解决方案是创建一个包含在Cat类中的内部类Claws,或者构建一个构造函数,其中包括Cat是否会刮伤。因此,我认为最佳的解决方案是创建一个内部接口ResetableContainer,它有一个方法reset,可以实现该方法以适应不同的类型。它可以保存过滤器需要存储的任何内容,并根据存储的内容执行重置。问题仍然是,我如何实现它,以避免存储单个输入或输入列表的不同可能性带来的所有这些复杂性?
看起来您遇到了一个概念设计问题,因为您希望过滤器的用户总是准确地知道它能做什么和不能做什么。但同时,你希望过滤器能够做很多不同的事情。。。这两个想法不能完全吻合

您可以创建这些“可选”方法,以便在执行时返回值:

/**
 * Resets the filter.
 *
 * @returns
 *          false if this operation is not supported by the filter
 */
public boolean reset() {
    return false;
}

一个更好的方法:包括一个必须被重写的附加方法,一个更常见的设计模式:请参阅以获取示例。如前所述,仅仅拥有一个以上的界面也可能很好。

这听起来像是学校的作业,所以你可能会受到某种程度的限制,你无法做到这一点,但我想 ld要做的是保持简单:单一接口:

public interface Filter<In, Out> {
    public Out filter(In toFilter);
    public void reset();
    public boolean canReset();
}
然后可能是一个抽象基类,为具有它们的方法提供良好的默认实现:

public abstract class BaseFilter<In, Out> implements Filter<In, Out> {
    public void reset() {}
    public boolean canReset() { return false; }
}

我甚至不会包括canReset,除了有时可重置有时不可重置的过滤器。如果这不是您想要支持的可能性,那么您可以删除canReset,只要是可重置的过滤器,只要您想重置它,就随时调用reset。

我不清楚为什么您不能只使用一种重置方法,对没有意义的过滤器不做任何操作。在一般的接口中,你总是会遇到这种情况。例如,并非InputStream的所有实现都实现了标记或重置。另一种看待它的方式是,所有过滤器都支持重置,但在大多数情况下,重置是不可操作的。可以通过多种方式实现良好的抽象。