• 1000 Мне не разрешено раскрывать информацию :) Поэтому, пожалуйста, не думайте, что это ЕДИНСТВЕННЫЙ код в моей гигантской кодовой базе, и предлагайте решения, которые сокращают углы или изменяют части дизайна, которые я упомянул, не могут быть изменены из-за внешних ограничений.
Факты:
У меня есть служебный класс, в нем есть несколько методов c, они используют одноэлементный ресурс:
public final class Utility
{
private static final Resource RES = Resource.getInstance();
private Utility() {} // Prevent instantiating Utility
public static boolean utilMethodOne() { return RES.isSomething(); }
public static int utilMethodTwo() { RES.getNumThings(); }
...
public static void utilMethodInfinity() { ... }
}
Утилита находится в библиотеке JAR, которая используется несколькими приложениями в большой кодовой базе - скажем, порядка 10 000 вызовов ее методов c stati, например: if (Utility.utilMethodOne ()) {.. .}
Resource - это внешний класс из другой библиотеки JAR.
Resource также имеет метод Resource.getInstance (String name), который возвращает именованный экземпляр, который может относиться к другому базовому ресурс на основе имени (внутри он хранит именованные ресурсы на карте ).
Resource.getInstance () возвращает эквивалент Resoruce.getInstance (""), также известный как экземпляр по умолчанию.
Ситуация:
Утилита должна быть улучшена, чтобы теперь она могла выполняться с одним из нескольких ресурсов, поэтому я планирую сделать утилиту экземпляром класса с нестатической c переменной-членом ресурса. Примерно так:
public final class Utility
{
private Resource res;
public Utility(String resName)
{
this.res = = Resource.getInstance(resName);
}
public boolean utilMethodOne() { return this.res.isSomething(); }
public int utilMethodTwo() { this.res.getNumThings(); }
...
public void utilMethodInfinity() { ... }
}
Теперь все в порядке, и я могу начать создавать служебные объекты, которые обращаются к их указанному ресурсу, а не только к ресурсу по умолчанию. Однако, как я уже упоминал, 10–100 тысяч вызовов методов теперь недействительны, поскольку они вызывали методы stati c!
Проблема:
Мой план заключалась в том, чтобы сохранить методы stati c в Utility и заставить их использовать экземпляр по умолчанию из Resource, при этом добавляя нестандартные c варианты для созданных экземпляров объектов Utility, которые используют свою «локальную» ссылку на ресурс.
// Best of both worlds:
public static boolean utilMethodOne() { return RES.isSomething(); }
public boolean utilMethodOne() { return this.res.isSomething(); }
Может, я тоже не могу съесть свой торт:
error: method utilMethodOne() is already defined in class Utility
public static boolean utilMethodOne(String sql)
Так что, похоже, мне придется либо ...
- Представить совершенно новый класс BetterUtility для мест, которые хотят использовать именованные ресурсы.
- Обновление 10,000 места для создания и использования измененного объекта Utility.
- ...? (подсказка: здесь и появляются ваши предложения!)
Мне действительно не нравятся 1 или 2 по разным причинам, поэтому мне нужно убедиться, что нет лучшего варианта 3 перед тем, как остановиться. Есть ли способ сохранить один класс, который в этом случае может предоставлять интерфейсы как stati c, так и non-stati c?
UPDATE 2020-06-01:
I Прихожу к выводу, что этого волшебного варианта 3 не существует. Итак, из двух моих первоначальных вариантов я думаю, что №2 является лучшим, поскольку это всего лишь одно усилие типа «просто убери с дороги и покончим с этим». Также включены некоторые из ваших предложений в дизайн (ы).
Итак, теперь, когда у меня есть направление по этому поводу, мне остается [надеюсь, только] еще одно ключевое решение ...
- Обновить все вызовы для создания новых объектов
// For a one-off call, do it inline
boolean foo = new Utility("res1").utilMethodOne();
// Or when used multiple times, re-use the object
Utility util = new Utility("res1");
boolean foo = util.utilMethodOne();
int bar = util.utilMethodTwo();
...
Учитывая количество / частоту использования, это похоже на потраченные впустую усилия на создание недолговечных объектов.
Следуйте шаблону, который использует сам ресурс, создав мою собственную именованную одноэлементную карту утилит (1: 1 с их соответственно названным ресурсом)
public final class Utility
{
private static final Map<String,Utility> NAMED_INSTANCES = new HashMap<>();
private Resource res;
private Utility(String resName)
{
this.res = Resource.getInstance(resName);
}
public static Utility getInstance(String resName)
{
synchronized(NAMED_INSTANCES)
{
Utility instance = NAMED_INSTANCES.get(resName);
if(instance == null)
{
instance = new Utility(resName);
NAMED_INSTANCES.put(resName, instance);
}
return instance;
}
}
public boolean utilMethodOne() { return this.res.isSomething(); }
public int utilMethodTwo() { this.res.getNumThings(); }
...
public void utilMethodInfinity() { ... }
}
// Now the calls can use
Utility.getInstance("res1")
// In place of
new Utility("res1")
Итак, по сути, это сводится к созданию объекта по сравнению с синхронизацией + поиском карты при каждом использовании. Вероятно, здесь немного преждевременной оптимизации, но мне, вероятно, придется придерживаться этого решения в долгосрочной перспективе.
ОБНОВЛЕНИЕ 2020-06-29:
Не хотел оставлять " Inte rnet тупик "здесь ... В конечном итоге я получил все сайты звонков, обновленные, как описано выше (включая вариант № 2 из обновления 2020-06-01). Он прошел все испытания и уже около недели работает в различных приложениях.