【问题标题】:Suggestions for implementing a solution using Singleton design pattern使用单例设计模式实现解决方案的建议
【发布时间】:2018-12-09 20:20:22
【问题描述】:

我需要实现一个解决方案作为测试框架的一部分,我正在考虑单例模式,原因如下所述。但是,我无法实现我的预期解决方案,因此需要一些关于可能实现的建议/输入。

问题陈述: 我有一个环境(我正在测试的产品的环境)配置属性文件,我想加载该文件并使测试框架可以全局访问参数的值。 我想使用单例模式,因为这些属性是一次性值(如果尝试多次初始化,应该报告异常),应该全局可用并且可以单点访问方法。

但是,属性/参数列表非常长,因此将其分解为模块(类)是明智的。对于下面的解释,我尝试了作文。

例如

public class Configuration {
    private static Configuration configObj;
    private static Database dbDetails;
    private static Machine macDetails;
    //...
    //... many more modules

    public static synchronized void createInstance(Properities envProps){
          //Should create only one instance of Configuration 
          // and should also initialize Database & Machine objects.
    }

    public static Configuration getConfigObject(){
         return configObj;
    }
}


public class Database {
    private static String dbConnectString;

    public Database(String dbcs){
         dbConnectString = dbcs;
    }

    public static String getDbConnectString(){
         return dbConnectString;
    }
}


public class Machine {
    private static String hostname;
    private static String loginUsername;

    public Machine(String hostname,String loginUsername){
        this.hostname = hostname; //It may include some trimming/cleaning
        this.loginUsername = loginUsername;
    }

    public static String getHostName(){
        return hostname;
    }
}

PS:只是一个键入的示例代码,用于理解我的问题陈述。

期望:现在的期望是,在尝试获取主机名时,我应该通过 Configuration 静态对象进行单点访问(假设我已成功初始化所有成员变量),即 p>

字符串主机名 = Configuration.getHostname();

字符串主机名 = Configuration.getConfigObject().getHostname();

当前问题: 如何使用组合或继承创建一个引用所有方法的静态对象(从概念上讲,组合是正确的方法)。

Multiple Inheritance 本来可以解决这个问题,但是 Java 不支持所以排除了。也不能考虑接口,因为重写所有方法既繁琐又冗长,而且参数/方法会随着时间不断变化。

欢迎所有建议,即使需要放弃此设计模式并尝试不同的东西。

【问题讨论】:

  • 简单地说:避免使用单例。将其设计为就好像您不需要单例一样工作。然后在一个将用于所有测试类的类中只初始化一次配置对象。
  • 只是为了澄清:你想要一个主Configuration 类,它将对自身的静态调用转换为对其静态成员(模块)的静态调用?你所说的参数/方法会随着时间不断变化是什么意思?
  • @DevCybran,第一个问题是。对于第二个问题,我已经有接近 150 个参数,这些参数会随着时间的推移而增长,而且参数名称也可能会改变(尽管很少)。如果我实现接口,我将不得不覆盖在实现类中的所有接口中声明的所有方法,比如配置,以提供定义&在这种情况下这似乎是多余的工作(高维护)&违背了模块的目的。

标签: java design-patterns singleton test-framework


【解决方案1】:

您将无法“自动”将静态调用委托给模块。即使调用不是静态的,正如你所说,Java 也不支持多重继承。

选项 1:

让您的主要Configuration 类提供将实例返回到您的模块的静态方法。每当您想读取配置条目时,首先获取模块实例,然后查询条目本身:

Configuration.getDatabaseConfiguration().getServerName();

这种方法的优点是非常清楚你所指的配置的哪一部分。如果只使用Configuration.getServerName(),则无法区分是要检索数据库的服务器名称还是网络服务器的名称。

选项 2:

如果您能够使用 Java 8 并且您的配置很大但非常简单(在编译时静态已知或可从极少数实例中提取),您可以考虑使用新的默认接口方法 (https://blog.idrsolutions.com/2015/01/java-8-default-methods-explained-5-minutes/)。

然后,您将为每个模块创建一个接口,其中所有 getter 都有默认实现。您的主配置类将实现所有模块接口,而不会覆盖任何方法。这样就可以从一个对象中查询到所有的配置条目,但是你仍然需要通过静态方法来获取这个对象。这与您可以获得的多重继承一样接近。不过我肯定会推荐选项 1。

【讨论】:

  • 感谢@DevCybran,我正在实施选项 1 本身。由于我只想将此配置加载一次(单例),因此我现在有一个静态的最终布尔标志,参数化构造函数在此基础上加载所有这些属性或报告异常。在获取详细信息时,它的作用与您提到的相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
相关资源
最近更新 更多