javadesign-patternssingletontest-framework

Suggestions for implementing a solution using Singleton design pattern


I need to implement a solution as part of Test framework & I am considering singleton pattern for reasons explained below. However, I am not able to achieve my intended solution & therefore would need some suggestions/inputs on possible implementations.

Problem Statement : I have a environment (env of the product I am testing) configuration properties file which I want to load & make the value of the parameters accessible globally to the test framework. I figured using the singleton pattern because these properties are one-time values (should report an exception if tried to initialize more than once), should be available globally & have an one-point access to the methods.

However, the list of properties/parameters is really long & therefore it's wise to break it into modules (classes). For the below explanation, I tried with composition.

For e.g.

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: Just a sample typed-in code for the understanding of my problem statement.

Expectation : The expectation now is that when trying to get the hostname, I should have a single point of access via Configuration static object (assuming that I have initialized all member variables successfully) i.e.

String hostname = Configuration.getHostname();

OR

String hostname = Configuration.getConfigObject().getHostname();

Current Issue : How to create one static object that will refer to all methods using either composition or inheritance (Conceptually, composition would be the right approach).

Multiple Inheritance would have solved the issue but Java doesn't support so ruled out. Cannot consider Interfaces either because overriding all methods is tedious & lengthy & the parameters/methods will keep changing over-time.

All suggestions are welcome even if it requires to scrap this design pattern & try something different.


Solution

  • You will not be able to "automatically" delegate static calls to modules. And even if the calls were not static, as you stated, Java does not support multiple inheritance.

    Option 1:

    Have your main Configuration class provide static methods that return instances to your modules. Whenever you want to read a configuration entry, first get the module instance, then query the entry itself:

    Configuration.getDatabaseConfiguration().getServerName();
    

    This method has the advantage that it is very clear which part of your configuration you are referring to. If you would just use Configuration.getServerName(), you cannot distingish whether you want to retrieve the database's server name, or the webserver's.

    Option 2:

    If you are able to use Java 8 and your configuration is large, but very simple (statically known at compile time or extractable from very few instances), you could consider using the new default interface methods (https://blog.idrsolutions.com/2015/01/java-8-default-methods-explained-5-minutes/).

    You would then create an interface for each module, where all getters have default implementations. Your main configuration class would implement all the module interfaces without overriding any of the methods. This way all configuration entries can be queried from one object, but you still have to obtain this object by a static method. This is as close to multiple inheritance as you can get. I would definitely recommend option 1 though.