Предложения по реализации решения с использованием шаблона проектирования Singleton

Мне нужно реализовать решение как часть тестовой среды, и я рассматриваю одноэлементный шаблон по причинам, описанным ниже. Однако я не могу достичь намеченного решения, поэтому мне понадобятся некоторые предложения/входы по возможным реализациям.

Постановка проблемы: у меня есть файл свойств конфигурации среды (env продукта, который я тестирую), который я хочу загрузить и сделать значения параметров доступными глобально для тестовой среды. Я решил использовать шаблон singleton, потому что эти свойства являются одноразовыми значениями (должны сообщать об исключении при попытке инициализации более одного раза), должны быть доступны глобально и иметь одноточечный доступ к методам.

Однако список свойств/параметров очень длинный, поэтому разумно разбить его на модули (классы). Для приведенного ниже объяснения я попытался с композицией.

Например,

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.getHostname();

OR

Строковое имя хоста = Configuration.getConfigObject().getHostname();

Текущая проблема: как создать один статический объект, который будет ссылаться на все методы, используя либо композицию, либо наследование (Концептуально, композиция была бы правильным подходом).

Множественное наследование решило бы проблему, но Java не поддерживает, что исключено. Также нельзя рассматривать интерфейсы, потому что переопределение всех методов утомительно и долго, а параметры/методы будут меняться с течением времени.

Приветствуются все предложения, даже если для этого требуется отказаться от этого шаблона проектирования и попробовать что-то другое.


person palkarrohan    schedule 19.11.2015    source источник
comment
Просто: избегайте использования Singleton. Спроектируйте это так, как будто вам не нужен синглтон. Затем инициализируйте один объект конфигурации только один раз в классе, который будет использоваться во всех ваших тестовых классах.   -  person Luiggi Mendoza    schedule 19.11.2015
comment
Просто для пояснения: вам нужен один основной класс Configuration, который переводит статические вызовы самого себя в статические вызовы своих статических членов (модулей)? И что вы подразумеваете под параметрами/методами, которые будут меняться со временем?   -  person Cybran    schedule 19.11.2015
comment
@DevCybran, да, на первый вопрос. Что касается второго вопроса, у меня уже есть около 150 параметров, которые со временем будут расти, а также имена параметров могут меняться (хотя и редко). Если я реализую интерфейсы, мне придется переопределить все методы, объявленные во всех интерфейсах в реализованном классе, скажем, Конфигурация, чтобы предоставить определение, что в этом случае кажется избыточной работой (высокое обслуживание) и побеждает цель модулей.   -  person palkarrohan    schedule 19.11.2015


Ответы (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/).

Затем вы должны создать интерфейс для каждого модуля, где все геттеры имеют реализации по умолчанию. Ваш основной класс конфигурации будет реализовывать все интерфейсы модулей без переопределения каких-либо методов. Таким образом, все записи конфигурации могут быть запрошены из одного объекта, но вам все равно придется получать этот объект статическим методом. Это максимально близко к множественному наследованию. Я бы определенно рекомендовал вариант 1, хотя.

person Cybran    schedule 19.11.2015
comment
Спасибо @DevCybran, я реализую вариант 1. Поскольку я хотел, чтобы эта конфигурация загружалась только один раз (Singleton), теперь у меня есть статический окончательный логический флаг, на основе которого параметризованный конструктор загружает все эти свойства или сообщает об исключении. И при получении деталей он делает то же самое, что вы упомянули. - person palkarrohan; 30.11.2015