Pergunta

Eu criei minha própria implementação de árvore para e vêm-se com duas classes, uma classe 'base' que é um nó de árvore genérica que está repleto de lógica e outra classe que estende aquela que é mais especializado.

Na minha classe base certos métodos envolvem instanciar novos nós de árvore (por exemplo, a adição de crianças). Estes instantations são lógica dentro (em um loop aninhado, digamos) que torna a lógica difícil de separar do instantation.

Então, se eu não substituir essas instantations na classe específica o tipo errado de nó será criado. No entanto, eu não faço deseja para substituir esses métodos porque eles também continha lógica compartilhada que não deve ser duplicada!

O problema pode ser resumido a isto:

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'

A primeira coisa que me veio à cabeça teria um 'criar gancho' que as classes estendendo poderia substituir:

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

Agora. enquanto ele era um bom primeiro pensamento, há um mau cheiro saindo de que o código algo terrível. Há algo de muito ... errado sobre isso.

É como cozinhar enquanto naked-- parece perigoso e desnecessário .

Assim, como você lidar com esta situação?

Foi útil?

Solução

Assim, depois de receber minha cópia do Design Patterns e abri-lo para o que eu estou bastante certo é a primeira vez que eu descobri o que eu quero.

É o chamado Factory Method e é principalmente um ajuste perfeito. Ainda é um pouco feio, porque o meu super-classe (Foo no exemplo acima) não é abstrato que significa que subclasses não são obrigados a implementar o gancho.

Isso pode ser corrigido com um pouco de refatoração, porém, e eu vou acabar com algo no sentido de:

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'!

Outras dicas

Além do padrão de fábrica, eu tomaria um olhar para o padrão Composite - ele tende a dar-se bem a trabalhar com uma fábrica em situações baseadas em árvores

.

Composite Design Pattern

Eu não acho que há uma abordagem melhor. Só tome cuidado para não chamar esses ganchos do construtor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top