Шаблонный шаблон для статических классов
У меня есть класс утилит, которые выполняют некоторую работу. Очевидно, что он закрыт для расширения и все методы являются статическими. Для простоты класс выглядит так:
public final class Util {
private Util() { }
public static void doWork() {
// some work
int variable = help();
// some work uses variable
}
private static int help() {
// some helper functionality
}
}
У класса есть метод doWork
который выполняет много расчетов. Кстати, метод вызывает вспомогательный метод help
чтобы получить некоторый результат, а остальную часть кода используйте результат, возвращаемый help
метод.
Теперь в клиентском коде я хочу повторно использовать функциональность метода doWork
но вместо звонка help
Я хочу позвонить help2
метод. Самое простое решение - просто создать метод doWork2
с заменой help
в help2
,
Это очень плохой подход, потому что каждое изменение в doWork
должен быть воспроизведен в doWork2
или. Это очень похоже на Template Method
шаблон, но из-за того, что у нас нет здесь расширения, мы не можем его применить.
Лучшее решение, которое я придумал, чтобы добавить параметр к этому методу, но сохранить всех существующих пользователей doWork
:
public static void doWork() {
doWorkWithParameter(true);
}
public static void doWorkWithParameter(boolean helpOrHelp2) {
// some work
int variable = helpOrHelp2 ? help() : help2();
// some work uses variable
}
Какие лучшие дизайнерские решения могут быть применены для решения этой проблемы? Есть ли способ добиться гибкости, как Template Pattern
имеет, но в приложении к утилитам классов.
Заранее спасибо.
3 ответа
Мое предложение вдохновлено шаблоном Command, где класс Util является Invoker, а каждая пара doWork-help инкапсулирована с использованием интерфейса Worker.
Рабочий интерфейс может быть чем-то вроде
public interface Worker {
public void doWork();
public int help();
}
Утиль Класс
public final class Util {
private Util() { }
public static void toWork(Worker worker){
worker.doWork();
}
}
Бетонщик (реализации справки и doWork)
public class ConcreteWorker implements Worker{
@Override
public void doWork() {
// TODO Auto-generated method stub
int variable = help();
}
@Override
public int help() {
// TODO Auto-generated method stub
return 0;
}
}
Другой работник
public class ConcreteWorker2 implements Worker{
@Override
public void doWork() {
// TODO Auto-generated method stub
int variable = help();
}
@Override
public int help() {
// TODO Auto-generated method stub
return 1;
}
}
И казнь
Util.toWork(new ConcreteWorker());
Util.toWork(new ConcreteWorker2());
Не так давно я сделал это:
public static enum Helper{
OLD(){
public int help(){
return 0;
}
},
NEW(){
public int help(){
return 1;
}
};
public abstract int help();
public void doWork() {
int variable = help();
}
}
public static Helper HELPER = Helper.NEW;
тогда мы можем позвонить:
Constants.HELPER.doWork()
Переключая значения констант HELPER, я могу изменить поведение. или вы можете сделать:
Helper.OLD.doWork();
Helper.NEW.doWork();
Вы можете создать 2 статических объекта Help1
& Help2
реализации Help
интерфейс, который имеет метод help() и измените ваш метод doWorkWithParameter следующим образом:
public static void doWorkWithParameter(Help h) {
int variable = h.help();
}
Это тесно связано с вашим текущим решением. Но я думаю, что это немного более "объектно-ориентированный".