Имеет ли смысл использовать паттерн состояний с виртуальными прокси?
class HeavyweightObjcet
{
public void operate() {
System.out.println("Operating...");
}
}
class LazyInitializer
{
HeavyweightObjcet objcet;
public void operate()
{
if (objcet == null)
objcet = new HeavyweightObjcet();
objcet.operate();
}
}
Здесь я создаю виртуальный прокси для тяжелого объекта. Каждый раз перед звонкомHeavyweightObject::operate
, программа сначала проверяет, является ли объект null
или не. Эта часть проверяется один раз и только один раз за все время существования объекта.
Возможное улучшение возможно с использованием такого паттерна состояний:
class HeavyweightObjcet
{
public void operate() {
System.out.println("Operating...");
}
}
class LazyInitializer
{
HeavyweightObjcet objcet;
State state = new UninitializedState(this);
public void operate()
{
state.operate();
}
}
abstract class State
{
LazyInitializer initializer;
public State(LazyInitializer initializer)
{
this.initializer = initializer;
}
abstract void operate();
}
class UninitializedState extends State
{
public UninitializedState(LazyInitializer initializer) {
super(initializer);
}
@Override
public void operate() {
initializer.objcet = new HeavyweightObjcet();
initializer.state = new InitializedState(initializer);
initializer.operate();
}
}
class InitializedState extends State
{
public InitializedState(LazyInitializer initializer) {
super(initializer);
}
@Override
public void operate() {
initializer.objcet.operate();
}
}
Имеет ли смысл это решение?
Есть ли какие-нибудь улучшения в коде?
Есть ли примеры того, что было сделано раньше?
Это ненужное осложнение, оно того стоит или зависит от ситуации?
Это делает код быстрее? Я имею в виду, что дополнительные вызовы функций могут быть медленнее, чем просто условные.
1 ответ
Это ненужное усложнение, оно того стоит или зависит от ситуации?
Хотя вполне нормально иметь только 2 состояния при использовании паттерна состояний, в данном конкретном случае это определенно перебор по следующим причинам:
- Будет только один переход состояния из
UninitializedState
->InitailizedState
. однаждыHeavyWeightObjcet
был инициализирован, вы определенно не собираетесь чередовать переход отInitializedState
->UninitializedState
или наоборот - Есть причина, по которой у нас есть такие принципы дизайна, как YAGNI (он вам не понадобится) и KISS (будь простым, глупым). Не вводите сложностей на первой итерации кода. Позвольте дизайну развиваться в рамках непрерывного рефакторинга.
- Хотя приведенный выше пример хорошо выглядит на бумаге, реальный мир - это совсем другая игра. В коде реального мира есть более важные проблемы. (Например, это
operate
метод потокобезопасный?)
Это делает код быстрее? Я имею в виду, что дополнительные вызовы функций могут быть медленнее, чем просто условные.
Когда дело доходит до производительности, это слишком маленькая область, чтобы беспокоиться о ней. Прочтите: микрооптимизация
И последнее, но не менее важное: паттерн состояний позволяет нам придерживаться принципа " открыт-закрыт".. В приведенном примере нет убедительной причины дляoperate
метод изменить до инициализации HeavyWeightObject
обеспокоен. Более того, код инициализации должен быть в конструкторе, а не вoperate
метод в первую очередь.