Имеет ли смысл использовать паттерн состояний с виртуальными прокси?

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 состояния при использовании паттерна состояний, в данном конкретном случае это определенно перебор по следующим причинам:

  1. Будет только один переход состояния из UninitializedState -> InitailizedState. однаждыHeavyWeightObjcet был инициализирован, вы определенно не собираетесь чередовать переход от InitializedState -> UninitializedState или наоборот
  2. Есть причина, по которой у нас есть такие принципы дизайна, как YAGNI (он вам не понадобится) и KISS (будь простым, глупым). Не вводите сложностей на первой итерации кода. Позвольте дизайну развиваться в рамках непрерывного рефакторинга.
  3. Хотя приведенный выше пример хорошо выглядит на бумаге, реальный мир - это совсем другая игра. В коде реального мира есть более важные проблемы. (Например, этоoperate метод потокобезопасный?)

Это делает код быстрее? Я имею в виду, что дополнительные вызовы функций могут быть медленнее, чем просто условные.

Когда дело доходит до производительности, это слишком маленькая область, чтобы беспокоиться о ней. Прочтите: микрооптимизация

И последнее, но не менее важное: паттерн состояний позволяет нам придерживаться принципа " открыт-закрыт".. В приведенном примере нет убедительной причины дляoperate метод изменить до инициализации HeavyWeightObjectобеспокоен. Более того, код инициализации должен быть в конструкторе, а не вoperate метод в первую очередь.

Другие вопросы по тегам