为具有不同参数的方法设计接口

时间:2011-07-10 06:34:48

标签: java design-patterns interface parameters

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

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

将按顺序应用其中一些过滤器。我还想为其他人提供某种一致的界面来编写自己的(可能是一般的)过滤器。我该怎么做呢?

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

mesh = smoothingFilter1.filter(mesh, booleanParam);

但可能完全不同:

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

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

是否有处理此类情况的设计模式?

3 个答案:

答案 0 :(得分:4)

实际上你根本不需要这些参数。 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.
}

答案 1 :(得分:1)

另一种方法(我并不十分热衷)是将参数捆绑在一个对象中,并使用多态来为不同的对象传递不同的参数。

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

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<P extends Parameters>,并且拥有List<FilterWithParams<?>>。在这一点上,你基本上彻底改造了M. Platvoet的解决方案!

答案 2 :(得分:1)

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

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.
}

Rossum的