Какой шаблон проектирования я должен использовать для выполнения задачи ниже - PullRequest
2 голосов
/ 17 февраля 2010

Мне нужно уметь условно выполнить метод. Я предпочитаю не иметь в своем коде кучу операторов IF по нескольким причинам. Наиболее заметным является то, что в определенный момент в будущем метод больше не будет использоваться.

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

Приложение, на которое я ссылаюсь, представляет собой приложение, которое заменит устаревшую систему. Устаревший код будет отключен и больше не будет использоваться в какой-то момент. Когда наступит этот момент времени, я не хочу возвращаться и менять какой-либо код (если это вообще возможно).

Вот псевдо-концептуальный пример того, что я имею в виду:

NewSystemEmployee.Save(Employee e)

if (Legacy System Is Running)
{
    LegacySystemEmployee.Save(Employee e)
}

Метод NewSystemEmployee.Save всегда должен выполняться. Я только хочу выполнить LegacySystemEmployee.Save, пока работает система Legacy. Когда система Legacy закрывается, я больше не хочу выполнять LegacySystemEmployee.Save

Как только устаревшая система исчезнет, ​​я не знаю, как мне достичь того, чего я хочу, без:

  1. Создание оператора IF перед вызовом LegacySystemEmployee.Save ИЛИ
  2. Удаление каждого вызова метода LegacySystemEmployee.Save ИЛИ
  3. Изменение метода LegacySystemEmployee.Save таким образом, чтобы он был заглушкой и ничего более

У меня также есть требование, чтобы класс NewSystemEmployee никоим образом не ссылался на класс LegacySystemEmployee.

Есть предложения?

Большое спасибо

Ответы [ 6 ]

6 голосов
/ 17 февраля 2010

На первый взгляд это требует шаблон стратегии (или фактически шаблонный метод ), возможно, с фабричным методом , чтобы контролировать, какую стратегию использовать. Пример (в псевдо-Java):

class Saver {
    protected void LegacySave(Employee e)  {}
    public final void Save(Employee e) {
        NewSystemEmployee.Save(e);
        LegacySave(e);
    }
}

class LegacySaver extends Saver {
    protected void LegacySave(Employee e) {
        LegacySystemEmployee.Save(e);
    }
}

Поскольку в какой-то момент вам больше не понадобится унаследованный вызов, имеет смысл реализовать значение по умолчанию LegacySave как пустое. Тогда вы можете тривиально использовать класс следующим образом:

getSaver().save(employee);

где getSaver() - это фабричный метод, который молча решает, какую реализацию Saver представить его вызывающей стороне. Тривиально он может получить имя класса из файла конфигурации.

Вопрос в том, как вам нужно изменить поведение: время выполнения или перезапуск приложения? Если вы можете перезапустить приложение, легко изменить эту строку в конфигурации, которая управляет используемой стратегией. Изменение поведения на лету немного сложнее, но выполнимо.

Многое зависит от того, какой язык программирования вы используете. Например. в Java / C ++ / C # вы можете легко выполнить то, что вы хотите, с помощью внедрения зависимостей ; на некоторых других языках это может быть не так просто.

1 голос
/ 17 февраля 2010
0 голосов
/ 17 февраля 2010

Ну, сразу два решения приходят мне на ум:

  • Используйте условную компиляцию, если она доступна, например, (С #)
#if (legacy)
   LegacySystemEmployee.Save(Employee e)
#endif
  • Создайте новый метод SaveEmployee, например (С #)
public static SaveEmployee(Employee e) {
    NewSystemEmployee.Save(Employee e)

    if (Legacy System Is Running) { LegacySystemEmployee.Save(Employee e) }
}

В дополнение к этому вы можете создать «интерфейс службы», который инкапсулирует все методы, которые вызывают обе системы. И, очевидно, вы можете объединить методы в один, например, (С #)

public static SaveEmployee(Employee e) {
    NewSystemEmployee.Save(Employee e)

#if (legacy) 
    LegacySystemEmployee.Save(Employee e) 
#endif
}

Для того чтобы условный код был активным, вы должны определить устаревший идентификатор, используя

#define legacy

или как условный символ компиляции во время компиляции.

0 голосов
/ 17 февраля 2010

Я бы выбрал простой прокси, который выглядит как устаревшая система, но проверяет, работает ли он, и в этом случае делегирует ему действие:

class LegacySystemEmployeeProxy {
    public Save(Employee employee) {
        if (Legacy System Is Running) {
            LegacySystemEmployee.Save(employee)
        }
    }
}

Теперь ваш исходный код уменьшается до:

NewSystemEmployee.Save(employee)
LegacySystemEmployeeProxy.Save(employee)

Когда устаревшая система исчезнет, ​​вы можете изменить LegacySystemEmployeeProxy.Save на пустой метод.

0 голосов
/ 17 февраля 2010

Я думаю, что наиболее подходящим шаблоном для вашей ситуации является комбинация шаблона проектирования стратегии & шаблона проектирования фабричного метода

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

Если вы используете Java / C #, вы можете использовать инструмент IoC, например, Unity или spring вместо / в дополнение к вашей фабрике

0 голосов
/ 17 февраля 2010

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

...