这是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个输出的元素,然后为每个实例化的元素命名,如果有输入,指定提供输入的元素的名称。

    我不清楚的是如何在程序运行时进行耦合。也许要走的路是拥有许多接口,例如AppleConsumerApplePieConsumer等,因此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/

  • 10-12 02:20