繁体   English   中英

构造 java 类以避免 instanceOf

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM