这更像是一个设计问题而非图形问题,但这里有一些背景知识:我正在使用OpenGL(在Java中,使用JOGL)编写程序,可以从.obj文件加载网格并渲染它。到目前为止没有问题,但我需要能够对网格应用一系列过滤器或转换,例如
将按顺序应用其中一些过滤器。我还想为其他人提供某种一致的界面来编写自己的(可能是一般的)过滤器。我该怎么做呢?
主要问题是滤波器可能需要不同的参数集,例如一个平滑算法可能需要用户选择两个参数(在运行时,使用GUI),而另一个可能不需要。类似地,一些着色算法可能仅需要平滑网格和RGB颜色,另一种可能需要平滑网格和干净网格(它从中生成颜色)。所以电话可能看起来像:
mesh = smoothingFilter1.filter(mesh, booleanParam);
但可能完全不同:
mesh = smoothingFilter2.filter(mesh, intParam1, intParam2, floatParam);
显然我的代码需要能够调用一般的过滤方法。为Filter
定义一个抽象类或接口是不是一个好主意,它有一个未实现的方法来用某种控制类注册自己(及其所需的参数)?看起来很复杂,但我想不出任何其他方法让程序使用具有任意签名的过滤器方法。我甚至不确定这个想法会起作用......
是否有处理此类情况的设计模式?
答案 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的