这是Java中的一种设计模式问题。
我正在设计一个java .jar文件,用作管理和处理某种形式的数据的框架。我希望最终用户能够以某种方式在一定的约束下指示“管道”配置。这些部分是生产者和/或消费者,我知道如何实现它们,但是连接使我感到困惑……这是一个与我的应用程序类似的废话示例。
假设我实现了以下元素:
AppleTree
=>产生苹果ApplePieMaker
=>食用苹果,生产苹果派
ApplePress
=>食用苹果,生产苹果酒
AppleSave
=>存储苹果,苹果派或苹果酒
文件
AppleLoad
=>从AppleSave
ApplePieMonitor
=>以产生的苹果派以GUI格式在屏幕上显示苹果派现在,我希望用户能够指定以下内容:
AppleTree | ApplePress | AppleSave cider1.sav
(生产苹果,将其制成苹果酒,并将其保存到文件中)AppleTree | AppleSave apple1.sav
(生产苹果,将它们保存到文件中)AppleLoad apple1.sav | ApplePieMaker | ApplePieMonitor
(将保存的苹果,将其制成饼状,并在GUI中的屏幕上显示结果)AppleTree tree1,ApplePieMaker piemaker1
(生产苹果,将它们制成苹果派和苹果酒,将苹果,苹果派和苹果酒保存到单独的文件中,这些苹果派将在用户运行时选择到一个文件中,其他苹果将预先确定这些文件,并在GUI中的屏幕)
因此,我对如何构造配置文件有一个粗略的想法:将事物构造为最多具有1个输入和最多1个输出的元素,然后为每个实例化的元素命名,如果有输入,指定提供输入的元素的名称。
我不清楚的是如何在程序运行时进行耦合。也许要走的路是拥有许多接口,例如
AppleConsumer
,ApplePieConsumer
等,因此ApplePieMaker
将实现AppleConsumer
接口(包括consumeApple()
方法),而AppleTree
将实现AppleProducer
接口,该接口可以在启动时注册消费者,这样,每次AppleTree
产生一个苹果时,它都会列出其使用者列表,并在每个使用者上调用consumeApple()
,这样,该使用者就可以执行正确的操作,而AppleTree
不必知道他们在用苹果做什么。有什么建议?这种东西有名字吗?我对设计模式不是很有经验。
编辑:我的最终用户不了解也不在乎Java。他们只需要能够建立一个配置文件(我正在尝试使其尽可能简单,以便给他们提供一些很好的例子)并运行我的程序,该程序将读取该配置文件,构造元素,并将其钩住一起去。所有元素都在我的控制之下,我不需要支持插件,因此我不必太一般。
最佳答案
不久前,我遇到了这个问题,由于我的输入和输出可能是复数的,因此很难用Java明确地指定它。但是,当您确定只有一个输入和输出时(由于文件是一种特定的输出,对吗?),您可以尝试使用选中的泛型。
一个处理步骤的实现(我称之为过滤器)具有两个检查的类型参数:输入和输出(例如,假设它们都扩展了一个公共接口,并且对于您在系统中注入的每个新类型,您都将对该接口进行子类化) 。
public interface Filter<Input extends Type, Output extends Type> {
public Class<Input> getInputType();
public Class<Output> getOutputType();
public void process(Input in, Output out);
}
过滤器链就是(兼容的)
Filter
的数组。通过兼容,我希望对于每个过滤器,其输出与其跟随器输入的类型相同,第一个过滤器的输入与您的总体输入类型匹配,最后一个过滤器的输出与预期结果类型匹配。实际上,这很容易验证,因为我们使用的是检查的泛型。因此,过滤器链是另一个(复合)过滤器。复合过滤器的兼容性应在构造函数中检查,并最终确定化合物数组。没有准确的方法可以使用泛型来表达该构造函数的参数的“链接”属性(兼容性),因此您将不得不使用裸类型执行此操作,这有点不干净。
克服此限制的另一种方法是以更麻烦的编写为代价,更改过滤器的定义,如下所示:
public interface Filter<Input extends Type, Output extends Type> {
public Class<Input> getInputType();
public Class<Output> getOutputType();
public Output out process(Input in);
}
然后,我们必须将复合滤波器定义为滤波器对的集合,从而定义为:
public class CompoundFilter<Input extends Type, Output extends Type>
implements Filter<Input extends Type, Output extends Type> {
private final Filter<Input extends Type, ? extends Type> l;
private final Filter<Input extends Type, ? extends Type> r;
public <Median extends Type> CompoundFilter(
Filter<Input, Median> r,
Filter<Median, Output> l
) {
this.l = l;
this.r = r;
}
@SuppressWarnings("unchecked")
public Output out process(Input in) {
// Compute l(r(in)) = (l o r) (in)
return ((Output<Input,Type>) l).process(r.process(in));
}
}
因此,组成过滤器只是编写问题:
Filter<A,B> f1 = new FilterImpl<A,B>;;
Filter<B,C> f2 = new FilterImpl<B,C>;
// this is mathematically f2 o f1
Filter<A,C> comp = new CompoundFilter<A,C>(f1,f2);
关于java - 在运行时配置“管道”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/562404/