【问题标题】:Pass constant class as argument and store it将常量类作为参数传递并存储它
【发布时间】:2015-12-22 10:23:02
【问题描述】:

伪代码

提供的 sn-ps 将被视为伪代码。如果有不同的解决方案是解决此问题的标准方法,我持开放态度。

这是关于预期用途的:

一些澄清:

  • 每个应用程序将使用一个且仅一个配置。它不会在运行时更改。
  • Main.java 不允许@Override
  • Configuration.java 不能是 Interface,因为应为未覆盖的字段提供默认值。
  • Configuration.java 将从其当前的两个领域大幅增长。使构建器模式变得非常混乱。

Configuration.java

public class Configuration
{
    public static int getFoo () { return 1; }
    public static int getBar () { return 2; }
}

UserDefinedConfiguration.java

public class UserDefinedConfiguration extends Configuration
{
    @Override
    public static int getFoo () { return 3; }
}

Main.java

public final class Main {
    private final Configuration config;

    // default configuration
    public Main () {
        this (Configuration.class);
    }

    // user-defined configuration
    public Main (Class<? extends Configuration> config) {
        this.config = config;
    }

    // dummy-test
    public void printFoo () {
        System.out.println(config.getFoo());
    }
}

现在回到主要问题,如何做到这一点?如果没有(或通过ConfigurationgetFoo() 应该返回1,如果通过UserDefinedConfiguration 然后3

实现它的一种方法是存储Configuration 的实例。但是,当所有 getter 都是 static 时,它感觉是多余的。也不将它们设为static 也没有多大意义。

注意:This is taken into account.

【问题讨论】:

  • It doesn't make much sense to not have them as static either. - 为什么不呢?您希望拥有不同的配置集,并且我假设您只创建每个配置集一次,因此非静态方法的“开销”(如果有的话)和配置的一个实例的创建应该无关紧要。你会自动获得@Override 的干净解决方案。
  • 因为拥有多个Configurations 没有任何意义。这些方法直接属于Configuration。我并不真正担心“开销”。
  • 配置值是否需要存在于代码中?另一种方法是创建属性文件或哈希映射的层次结构,其中稍后读取的值会覆盖以前的值。然后,您不需要将继承建模为类/接口。只是猜测,可能我完全误解了这个问题......
  • 如果我理解正确的话,我想你已经明白了。 HashMap 做存储部分的问题是它可以包含整数、字符串、双精度数等等。另外,我希望它对现有的东西更加坚定。我的想法是我提供Configuration,如果一两件事不符合用户的要求,那么他们可以只覆盖这些内容,同时保持其他所有内容不变。我还需要确保在运行时不能更改Configuration。虽然仍然可以访问。

标签: java


【解决方案1】:

除非使用脏反射,否则恐怕您将不得不使用实例而不是类。来自@JonSkeet

单例允许访问单个创建的实例 - 该实例 (或者更确切地说,对该实例的引用)可以作为参数传递 到其他方法,并视为普通对象。

静态类只允许静态方法。

这正是您想要做的:将配置作为参数传递。


我将创建一个定义默认值的抽象类:

public abstract class Configuration {
  public int getFoo() { return 1; }
  public int getBar() { return 2; }
}

然后,每个具体配置一个单例:

public final class DefaultConfiguration extends Configuration {
  public static final Configuration INSTANCE = new DefaultConfiguration();
  private DefaultConfiguration() {}
  // nothing to override, use the default values
}

public final class UserDefinedConfiguration extends Configuration {
  public static final Configuration INSTANCE = new UserDefinedConfiguration();
  private UserDefinedConfiguration() {}
  @Override public int getFoo() { return 3; } // specific `foo` value
}

最后,在你的Main

public class Main {
  private final Configuration config;
  public Main() { this(DefaultConfiguration.INSTANCE); }
  public Main(Configuration config) { this.config = config; }
}

另外,请注意 Java 8 允许在接口中实现默认方法; Configuration 可以是一个接口:

public interface Configuration {
    default int getFoo() { return 1; }
    default int getBar() { return 2; }
}

【讨论】:

  • Java 8 中 interface 的好话,我不知道 default。并不是说在这种情况下它对我有帮助,因为我可以使用抽象类来产生相同的结果。
  • 我担心我不得不求助于反思来解决它“我的”方式。我不喜欢。
  • 我可以调用 new Configuration() 并在从 getter 中删除 static 时传递它,而不是使用单例。然而,再一次,这感觉很糟糕,而且它不是我想要完成的直接目标。然而,它最终会产生相同的结果。我确实在我的问题One way to accomplish it is to store an instance of Configuration. However, it feels redundant when all the getters are static. It doesn't make much sense to not have them as static either. 中简要提到了这一点,但是 Singletons 会让我解决实例化它两次的问题。
  • 我真的很想绕过必须创建配置文件的实例。现在这就是我想要的。我想要的与可能的/好的实践不同。我会考虑一下,多读一些,然后回复你。
【解决方案2】:

所以本质上,你需要一个类型而不是一个实例的多态性。在 Java 中,这通常使用泛型类型来完成:

class GenericMain<T extends Configuration>
{
    private final T config;
}

而且由于 Java 不允许默认的泛型参数,您必须定义另一个类来指定默认值:

class DefaultMain extends GenericMain<Configuration>
{
}

这些与您的 Main ()Main (Class&lt;? extends Configuration&gt; config) 构造函数一对一匹配。


或者,您可以存储Configuration 的实例并执行以下操作:

public class Configuration
{
    private final int foo = 1;
    private final int bar = 2;

    public final int getFoo () { return foo; }
    public final int getBar () { return bar; }

    public Configuration () {}

    protected Configuration (int foo) {
        this.foo = foo;
    }
}

public class UserDefinedConfiguration extends Configuration
{
    public UserDefinedConfiguration() {
        super(3);
    }
}

【讨论】:

  • 我不想以任何方式暴露这个Main。用户应该使用它的唯一方法是Main main = new Main();。此外,Configuration 类将有很多字段,很容易超过 100 个(是的,它们都直接相关 Main。即使使用 builder-pattern 也会使用户更改字段变得非常混乱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
相关资源
最近更新 更多