[英]Structuring java classes to avoid instanceOf
我正在尝试在 java 中创建一个应用程序,以加载和配置一系列不同的 GLSL 着色器。 目前我有类似下面的东西,但最终可能会有更多(30+)更多类似的类 - 每个加载一个单独的着色器。
理想情况下,我希望能够将着色器类放在一个列表中,并将它们链接到 GUI,以便可以检索和更新着色器参数。 除了相同的通用逻辑(加载 GLSL 文件并返回 PShader)之外,每个 class 的变量(和 getter/setter)可能完全不同(例如,我想使用的一些 GLSL 着色器没有变量,而其他可能有一个或多个变量 - float、boolean、int 等)。
我可以有某种基本的 class,并扩展 class 以处理不同的变量,但这仍然可能导致我在某些时候不得不管理某种类型的检查/使用一堆 instanceOf 语句。 我正在努力了解如何在这里轻松应用多态性。 我研究了 java 反射,但这并没有让我走得太远,并且一直在研究不同的设计模式。
注意 - 这不是家庭作业。 这只是一个个人项目。 所以,我不担心必须由其他人维护的东西,但它激起了我对不同设计模式的兴趣,我想知道是否有更好的方法来构建它。
public class ChromaColor {
private Shader shader;
private float smoothing;
public Chroma(){
shader = loadShader("chroma.glsl");
setSmoothing(0.1F);
}
public Chroma setSmoothing(float f) {
if(shader != null) shader.set("smoothing", f);
this.smoothing = f;
return this;
}
public float getSmoothing() {
return smoothing;
}
public Shader shader() {
return shader;
}
}
除了相同的通用逻辑(加载 GLSL 文件并返回 PShader)之外,每个 class 的变量(和 getter/setter)可能完全不同
……
我正在努力了解如何在这里轻松应用多态性。 我研究了 java 反射,但这并没有让我走得太远,并且一直在研究不同的设计模式。
您没有很多方法,因为您无法以统一的方式处理不同类的实例(获取和设置属性)。
您可以通过 class 定义一个渲染/处理 class 来处理。
优点:在编译时检查。
缺点:要编写很多重复的代码。
或者您使用反射来检索字段以在 GUI 中获取/设置。
优点:要编写的代码少得多。
缺点:编译时没有检查。
注 1)使用反射检索所有 getter/setter 可以检索您不想暴露给 GUI 的私有字段。
如果是这种情况,注释要包含或排除的字段可能是解决此问题的一种方法。
注意 2)如果您编写单元测试(可能是参数化测试)来检查要处理的不同类的实例的属性是否可以被 GUI 读/写,则可以减轻编译时不检查的缺陷。
使用java.util.Properties
的实例作为配置Shader
的唯一参数怎么样? 还是另一种java.util.Map
?
当着色器都具有一组简单的共同参数时(有些是全部,有些没有,有些是选择),您可以为配置创建某种类型的 DSL,它检查每个参数值,并且每个着色器类型在列出哪些 arguments 对其有效。
这将允许您尽可能多地重用您的代码。 它还允许拥有 getter 和 setter。 看看java.time
中的类,例如这看起来如何……
它可能看起来像这样:
public interface IChromaColors
{
Set<Parameter> getParameters();
void configure( Map<Parameter,Object> values );
Object get( Parameter parameter );
void set( Parameter parameter, Object value );
}
Parameter
可能如下所示:
public interface Parameter<T>
{
String getName();
Class<T> getType();
boolean validate( T value );
}
现在您的 class 可能如下所示:
public class ChromaColor implements IChromaColor
{
private Map<Parameter,Object> m_Values;
private Set<Parameter> m_ValidValues;
private Shader shader;
public Chroma( Map<Parameter,Object> values )
{
shader = loadShader("chroma.glsl");
m_ValidValues = Set.of( SmoothingParameter );
m_Values = values;
if( !m_Values.contains( SmootingParameter ) )
{
m_Values.put( SmoothingParameter, Float.valueOf( 0.1F ) );
}
configure( m_Values );
}
public Chroma set( Parameter parameter, Object value
{
if( m_ValidValues.contains( parameter )
{
…
}
return this;
}
public Object get( Parameter parameter )
{
return m_Values.get( parameter );
}
public Shader shader() {
return shader;
}
}
这只是我想法的原始,非常原始的草稿! 所以我省略了 generics Parameter
的问题,接口可以优化(显着)。 但我希望你能明白我的意思。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.