Шаблон проектирования для обработки настроек в подклассах? - PullRequest
5 голосов
/ 27 сентября 2010

У меня есть небольшая иерархия классов, которые реализуют общий интерфейс.

Каждый конкретный класс должен получить структуру настроек, содержащую, например, только открытые поля. Проблема в том, что настройка структуры

  • имеет часть, общую для всех классов
  • имеет другую часть, которая варьируется от одного конкретного класса к другому

Мне было интересно, был ли у вас какой-нибудь элегантный дизайн, чтобы справиться с этим. Я хотел бы построить что-то вроде:

BaseFunc doer = new ConcreteImplementation1();

с ConcreteImplementation1 реализует BaseFunc. И есть что-то вроде

doer.setSettings(settings)

но есть объект '' settings '', имеющий конкретную реализацию, подходящую для ConcreteImplementation1.

Как бы вы это сделали?

Ответы [ 6 ]

2 голосов
/ 27 сентября 2010

Это может быть именованный шаблон дизайна, если это так, я не знаю имени. Объявите абстрактный класс, который реализует желаемый интерфейс. Конструктор абстрактного класса должен взять экземпляр вашего объекта настроек, из которого он извлечет глобальные настройки. Получите один или несколько классов из абстрактного класса. Конструктор производного класса должен взять экземпляр объекта настроек, передать его конструктору родительского класса, а затем извлечь все локальные настройки.

Ниже приведен пример:

class AbstractThing implements DesiredInterface
{
    private String globalSettingValue1;
    private String globalSettingValue2;

    protected AbstractThing(Settings settings)
    {
        globalSettingValue1 = settings.getGlobalSettingsValue1();
        globalSettingValue2 = settings.getGlobalSettingsValue2();
    }

    protected String getGlobalSettingValue1()
    {
        return globalSettingValue1;
    }

    protected String getGlobalSettingValue2()
    {
        return globalSettingValue2;
    }
}

class DerivedThing extends AbstractThing
{
    private String derivedThingSettingValue1;
    private String derivedThingSettingValue2;

    public DerivedThing(Settings settings)
    {
        super(settings);
        derivedThingSettingValue1 = settings.getDerivedThingSettingsValue1();
        derivedThingSettingValue2 = settings.getDerivedThingSettingsValue2();
    }
}
1 голос
/ 27 сентября 2010

Имеют соответствующую иерархию объектов настроек, используйте Factory для создания настроек, соответствующих определенному классу.

1 голос
/ 27 сентября 2010

Похоже, вам нужен довольно стандартный Шаблон посетителя .

Проще говоря, предположим, что все ваши свойства хранятся в виде пар ключ-значение в картах.И у вас есть 3 класса в вашей иерархии: A, B, C. Все они реализуют некоторый общий интерфейс CI.

Затем вам нужно создать держатель свойства, подобный этому:

public class PropertyHolder {

    public Map<String, String> getCommonProperties () { ... }

    public Map<String, String> getSpecialPropertiesFor (CI a) { return EMPTY_MAP; }

    public Map<String, String> getSpecialPropertiesFor (A a) { ... }

    public Map<String, String> getSpecialPropertiesFor (B b) { ... }

    ...
}

ВсеВаши классы должны реализовать 1 метод getSpecialProperties, который объявлен в интерфейсе CI.Реализация так же просто, как:

public Map<String, String> getSpecialProperties (PropertyHolder holder) {
   return holder.getSpecialPropertiesFor (this);
}
0 голосов
/ 27 сентября 2010

Вы можете использовать Generics, чтобы определить, какие настройки нужны этому экземпляру. Примерно так:

public abstract class MySuperClass<T extends MySettingsGenericType>{
    public MySuperClass(T settings){
         //get your generic params here
    }

}

public class MyEspecificClass extends MySuperClass<T extends MySettingsForThisType>{
    public MySuperClass(T settings){
         super(settings);
         //Get your espefic params here.
    }

}

//and you could use this
BaseFunc doer = new ConcreteImplementation1(ConcreteSettingsFor1);

// Я не компилирую этот код и пишу в спешке. Извините, если есть какая-то ошибка ...

0 голосов
/ 27 сентября 2010

Я начал играть с новым шаблоном, который я назвал «карта типов объектов». Это как карта Java, но значения имеют тип. Это позволяет вам определять ключи, которые каждый класс хочет прочитать, и получать значения безопасным для типов способом (без затрат времени выполнения!)

Подробнее см. В моем блоге .

Приятно, что это все еще карта, так что вы можете легко реализовать наследование, уведомления и т. Д.

0 голосов
/ 27 сентября 2010

Я прошел по этому маршруту один раз. Это сработало, но после того, как решило, что оно того не стоит.

Вы можете определить базовый класс MyBean или что-то еще, и у него есть собственный метод mergeSettings. Каждый класс, который вы хотите использовать, может расширить MyBean и предоставить собственную реализацию для mergeSettings, которая вызывает суперклассы mergeSettings. Таким образом, общие поля могут быть в суперклассе. Если вы хотите стать по-настоящему модным, вы можете определить интерфейс и абстрагировать класс, чтобы он был действительно красивым. И пока вы на это, может быть, вы могли бы использовать отражение. в любом случае, mergeSettings получит карту, ключом которой является имя свойства. Каждый класс имеет свои константы, связанные с ключами.

 class MyBean extends AbstractMyBean ... {
       public static final String FIELD1 = 'field1'

       private String field1

       public mergeSettings(Map<String, Object> incoming) {
            this.field1 = incoming.get(FIELD1);
            // and so on, also do validation here....maybe put it on the abstract class
       }


 } 

Хотя для сеттеров очень много работы ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...