【问题标题】:Designing an interface for methods with different parameters为具有不同参数的方法设计接口
【发布时间】:2011-07-10 06:34:47
【问题描述】:

这更像是一个设计问题而不是图形问题,但这里有一点背景知识:我正在使用 OpenGL(在 Java 中,使用 JOGL)编写一个程序,它可以从 .obj 文件加载网格并渲染它.到目前为止没有问题,但我需要能够对网格应用一系列过滤器或转换,例如

  • 曲面细分
  • 向顶点添加随机噪声
  • 对噪声网格应用平滑算法
  • 为网格着色(可能基于也可能不基于平滑网格和原始干净网格)

将按顺序应用其中几个过滤器。我还想为其他人提供某种一致的接口来编写他们自己的(可能是通用的)过滤器。我该怎么办?

主要问题是过滤器可能需要不同的参数集,例如一种平滑算法可能需要用户选择两个参数(在运行时,使用 GUI),而另一种可能不需要。类似地,一些着色算法可能只需要平滑网格和 RGB 颜色,另一种可能需要平滑网格和干净网格(从中生成颜色)。所以调用可能看起来像:

mesh = smoothingFilter1.filter(mesh, booleanParam);

但可能完全不同:

mesh = smoothingFilter2.filter(mesh, intParam1, intParam2, floatParam);

显然我的代码需要能够调用通用过滤方法。为Filter 定义一个抽象类或接口,并使用未实现的方法将其自身(及其所需的参数)注册到某种控制类是一个好主意吗?看起来很复杂,但我想不出任何其他方法来让程序使用具有任意签名的过滤器方法。我什至不确定这个想法是否可行......

有处理这种情况的设计模式吗?

【问题讨论】:

  • 感谢您的回复,刚开始尝试这些东西,发现所有 3 个答案都很有用

标签: java design-patterns interface parameters


【解决方案1】:

其实你根本不需要参数。 Mesh filter(Mesh mesh); 就足够了。 将其他参数移动到过滤器的不同具体实现的构造函数中。

看起来像这样:

Filter smoothingFilter1 = new FirstFilter(booleanParam);    
mesh = smoothingFilter1.filter(mesh);

Filter smoothingFilter2 = new SecondFilter( intParam1, intParam2, floatParam);    
mesh = smoothingFilter2.filter(mesh);

对于实例化,您可以使用以下内容:

public interface AbstractFilterFactory {
  Params getRequiredParams();
  Filter createFilter(Params params);
}

public interface Params {
 // some interface that describes specific parameters that are required
 // probably a collection of Parameter classes which has name, type and value information. 
}

public class FirstFilterFactory implements AbstractFilterFactory {
  // return a concrete params object use that to instantiate a concrete filter.
}

【讨论】:

  • 谢谢,这使它更容易一些,但参数可能会在运行时发生变化,我希望创建过滤器的代码(即使用适当的参数调用那些构造函数)被封装在我的框架而不是在用户的代码中。此外,我的代码需要知道要放在 GUI 上的控件(例如滑块等)和参数名称,因此它需要提前知道它需要哪些参数作为输入。
  • @HappyPixel 添加了一些封装构造函数的方法。
【解决方案2】:

另一种方法(我不太喜欢)是将参数捆绑在一个对象中,并使用多态性为不同的对象传递不同的参数。

首先,一个快速而肮脏的版本,使用地图:

interface Filter {
    Mesh filter(Mesh input, Map<String, Object> params);
}

多态对象:

abstract class Parameters {
}

interface Filter {
    Mesh filter(Mesh input, Parameters params);
}

class FirstFilterParameters extends Parameters {
    private boolean booleanParam;
    // constructor, getter, possibly setter
}

class FirstFilter implements Filter {
    Mesh filter(Mesh input, Parameters params) {
        FirstFilterParameters ffParams = (FirstFilterParameters)params;
        boolean booleanParam = ffParams.getBooleanParam();
        // etc
    }
}

通过泛型实现类型安全的多态对象:

abstract class Parameters {
}

interface Filter<P extends Parameters> {
    Mesh filter(Mesh input, P params);
}

class FirstFilterParameters extends Parameters {
    private boolean booleanParam;
    // constructor, getter, possibly setter
}

class FirstFilter implements Filter<FirstFilterParameters> {
    Mesh filter(Mesh input, FirstFilterParameters params) {
        boolean booleanParam = params.getBooleanParam();
        // etc
    }
}

不过,带有泛型的版本使过滤器的多态处理变得更加困难。如果您想要一个过滤器列表和一个参数列表,并使用相应的参数应用每个过滤器,您会怎么做?没有办法安全地做到这一点。您必须做一些操作,例如将每一对打包成一个具有自己类型参数的对象,例如FilterWithParams&lt;P extends Parameters&gt;,并拥有一个List&lt;FilterWithParams&lt;?&gt;&gt;。至此,您基本上重新发明了 M. Platvoet 的解决方案!

【讨论】:

  • 不错的答案。在我看来,泛型解决方案比公认的答案更适合这个问题
【解决方案3】:

另一个类似的解决方案,没有泛型,是声明一个抽象参数类:

abstract class FilterParameters { }

你的界面看起来像:

interface Filter {
  Mesh filter(Mesh input, FilterParameters params);
}

对于需要的每组新参数,您声明一个新的 FilterParameters 子类,它可以携带所有必需的参数。

// Foo parameter only.
class FooFilterParameters extends FilterParameters { 
  public Foo getFoo() { }
  // Other stuff.
}

// Foo, Bar and int parameters.
class BarFilterParameters extends FilterParameters { 
  public Foo getFoo() { }
  public Bar getBar() { }
  public int getMagnification() { }
  // Other stuff.
}

每个过滤方法都需要检查其参数的类型:

// Foo filter
public Mesh filter(Mesh inMesh, FilterParameters fp) {
  if (!(fp instanceof FooFilterParameters)) {
    throw new IllegalParameterException("Not FooFilterParameters.");
  }
  // Foo filter code here.
}

玫瑰

【讨论】:

    猜你喜欢
    • 2013-02-02
    • 1970-01-01
    • 2012-02-25
    • 2013-04-14
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    相关资源
    最近更新 更多