Java 使用单例设计模式实现解决方案的建议

Java 使用单例设计模式实现解决方案的建议,java,design-patterns,singleton,test-framework,Java,Design Patterns,Singleton,Test Framework,我需要实现一个解决方案作为测试框架的一部分&出于下面解释的原因,我正在考虑单例模式。但是,我无法实现预期的解决方案&因此需要一些关于可能实现的建议/输入 问题陈述: 我有一个环境(我正在测试的产品的env)配置属性文件,我希望加载该文件并使测试框架能够全局访问参数值。 我认为使用单例模式是因为这些属性是一次性值(如果尝试多次初始化,则应报告异常),应该是全局可用的,并且对方法具有单点访问权限 但是,属性/参数的列表非常长&因此将其分解为模块(类)是明智的。对于下面的解释,我尝试了作文 例如 pu

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

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

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

例如

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:只是为了理解我的问题陈述而键入的代码示例

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

字符串hostname=Configuration.getHostname()

字符串hostname=Configuration.getConfigObject().getHostname()

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

多重继承本来可以解决这个问题,但Java不支持这种情况。不能考虑接口,因为重写所有方法都是冗长冗长的,参数/方法会随着时间的变化而变化。 欢迎所有建议,即使需要放弃此设计模式并尝试其他方法。

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

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

Configuration.getDatabaseConfiguration().getServerName();
这种方法的优点是可以非常清楚地知道您所指的是配置的哪一部分。如果只使用
Configuration.getServerName()
,则无法区分是要检索数据库的服务器名称还是Web服务器的名称

备选案文2:

如果你能够使用java 8,你的配置很大,但是非常简单(在编译时静态已知或者从非常少的实例中提取),你可以考虑使用新的默认接口方法().< /p>


然后,您将为每个模块创建一个接口,其中所有getter都有默认实现。主配置类将实现所有模块接口,而不重写任何方法。通过这种方式,可以从一个对象查询所有配置条目,但您仍然必须通过静态方法获取此对象。这与多重继承非常接近。不过,我绝对推荐选项1。

简单地说:避免使用Singleton。将其设计为工作状态,就像您不需要singleton一样。然后在一个类中只初始化一次单个配置对象,该类将在所有测试类中使用。只是为了澄清一下:您想要一个单一的main
configuration
类,该类将对自身的静态调用转换为对其静态成员(模块)的静态调用?你说的参数/方法会随着时间的推移而不断变化是什么意思?@DevCybran,第一个问题是肯定的。对于第二个问题,我已经有近150个参数,这些参数将随着时间的推移而增加&而且参数名称可能会改变(尽管很少)。如果我实现接口,我将不得不覆盖实现类中所有接口中声明的所有方法,比如配置,以提供定义&在这种情况下,这似乎是冗余工作(高维护)&违背了模块的目的。感谢@DevCybran,我正在实现选项1本身。因为我只想加载一次这个配置(单例),所以现在我有了一个静态的final Boolean标志,参数化构造函数将根据该标志加载所有这些属性或异常报告。在获取细节时,它的操作与您提到的相同。