2

私はさまざまな理由で独自のTree実装を作成し、2つのクラスを考え出しました。1つはロジックがぎっしり詰まったジェネリックツリーノードである「base」クラスで、もう1つはより特殊なクラスを拡張するクラスです。

私の基本クラスでは、特定のメソッドに新しいツリーノードのインスタンス化が含まれます(子の追加など)。これらのインスタンス化はロジック内にあり(たとえば、ネストされたループ内)、ロジックをインスタンス化から分離するのが困難になります。

したがって、特定のクラスでこれらのインスタンス化をオーバーライドしないと、間違ったタイプのノードが作成されます。ただし、これらのメソッドには、複製してはならない共有ロジックも含まれているため、これらのメソッドをオーバーライドしたくありません。

問題はこれに要約することができます:

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();
}

今。それは素晴らしい最初の考えでしたが、そのコードから何かひどい悪臭が出てきました。何か非常に...それについて間違っています。

それは裸で料理をするようなものです-それは危険で不必要だと感じます。

では、この状況にどのように対処しますか?

4

3 に答える 3

3

だから、私のデザインパターンのコピーを入手してそれを開いた後、私が欲しいものを発見したのはこれが初めてだと確信しています.

これは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'!
于 2008-09-29T09:44:04.387 に答える
1

Factory パターンに加えて、Composite パターンを見てみましょう。これは、ツリーベースの状況で Factory を操作するのに適している傾向があります。

複合設計パターン

于 2008-09-29T09:56:50.800 に答える
0

より良いアプローチはないと思います。これらのフックをコンストラクターから呼び出さないように注意してください。

于 2008-09-29T09:22:06.623 に答える