Можно ли иметь инстанцию ​​объекта «крючки» в базовых классах? - PullRequest
2 голосов
/ 29 сентября 2008

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

В моем базовом классе некоторые методы включают создание новых узлов дерева (например, добавление дочерних элементов). Эти экземпляры находятся внутри логики (скажем, во вложенном цикле), что затрудняет отделение логики от реализации.

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

Проблема может быть сведена к следующему:

public class Foo {
    public String value() { return "foo"; }

    public Foo doStuff() {
        // Logic logic logic..
        return new Foo();
    }
}

class Bar extends Foo {
    public String value() { return "bar"; } 
}

new Bar().doStuff().value(); // returns 'foo', we want 'bar'

Первым, что пришло мне в голову, будет «ловушка создания», которую расширяющие классы могут переопределить:

public Foo createFooHook(/* required parameters */) {
  return new Foo();
}

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

Это похоже на приготовление пищи в обнаженном виде - кажется опасным и ненужным .

Итак, как бы вы справились с этой ситуацией?

Ответы [ 3 ]

3 голосов
/ 29 сентября 2008

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

Он называется Factory Method , и в основном он идеально подходит. Это все еще немного некрасиво, потому что мой суперкласс (Foo в приведенном выше примере) не является абстрактным, что означает, что подклассы не обязаны реализовывать ловушку.

Хотя это можно исправить с помощью некоторого рефакторинга, и в итоге я получу кое-что с эффектом:

abstract class AbstractFoo {
    public String value() { return "Foo"; }

    public AbstractFoo doStuff() {
        // Logic logic logic
        return hook();
    }

    protected abstract AbstractFoo hook();
}

class Foo extends AbstractFoo {
    protected AbstractFoo hook() { return new Foo(); }
}

class Bar extends AbstractFoo {
    public String value() { return "Bar"; }

    protected AbstractFoo hook() { return new Bar(); }
}

new Bar().doStuff().value(); // Returns 'Bar'!
1 голос
/ 29 сентября 2008

В дополнение к шаблону Factory я бы взглянул на шаблон Composite - он хорошо подходит для работы с Factory в древовидных ситуациях.

Составной шаблон дизайна

0 голосов
/ 29 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...