2016-12-30 3 views
1

直感的には、再帰を使用して最良に解決されるという問題があるとします。私はまた、コードのテスト可能にするために、依存関係の注入を使用しようとしているどのようにしてコンテキストコールを複数のメソッド呼び出しに渡すのを避けるには?

Foo foo = new Foo(new Bar(new Baz())); 

:バズがfooに依存してwan't場合、

class Foo { 

    Bar bar; 

    Foo(Bar bar) { 
     this.bar = bar; 
    } 

    ResultType doFoo() { 
     ...stuff... 
     bar.doBar(); 
    } 

} 

class Bar { 

    Baz baz; 

    Bar(Baz baz) { 
     this.baz = baz; 
    } 

    ResultType doBar() { 
     ...stuff... 
     baz.doBaz(); 
    } 
} 

class Baz { 

    Foo foo; 

    Baz(Foo foo) { 
     this.foo; 
    } 

    ResultType doBaz() { 
     if (foo is needed) { 
      foo.doFoo(smaller problem) 
     } else { 
      ...stuf... 
     } 
    } 
} 

さて、あなただけの何かのように行うことができますBazは任意のFooを取ることができるので、一番上のものを取得してループを形成すれば問題ありません。

(JVMはループIIRCを処理できます)。 BazだけがFooが必要かどうか判断できます。

Fooをテストする方法でFooをBazに導入する最もクリーンな方法は何ですか?

FooパラメータをdoBaz()に追加していますか? (?fooが続いなどdoBaz、に渡しdoBarに「これを」渡す必要があります...またはより良い方法があることを示唆している)

EDIT:

おそらく、問題の説明は確かだろう便利である。

アルゴリズムは基本的にコンパイラであり、コードを入力として受け取り、コードの意味を表すデータ構造を出力します。このデータ構造は性質上非常に再帰的です。

しかし、コードに不明瞭さがある可能性があります(宣言されていないメソッドを考えてください)。この問題を引き起こしたのは、ほとんどのコンパイラとは異なり、このコードは単にユーザーに一連のエラーを吐いてはならず、代わりにコードを入力するオプションを提供するということです。

基本的に、コンパイラは「メイン」コードのコンパイルを一時的に停止し、ユーザーが提供するこの新しいコードのコンパイルを開始します。その後、結果のデータ構造を「メイン」データ構造に添付します。

ユーザーが提供するこのコードの中に、より多くの不明瞭性がある場合、これによりユーザーは明確にすることができます。

基本的に、コードが不完全であることを認識するコンポーネント(Bazによってreprezented)は、ユーザーが提供するコードのコンパイルを開始するために「メイン」コンポーネント(Foo)を呼び出す必要があります。

+0

あなたが実際の問題をより詳細に記述した場合はおそらく役に立ちます。周期的ではない分解がある可能性があります。 – chrylis

+0

さて、完了です。プロセス自体がユーザに見えるような方法で再帰的なので、おそらく再帰アルゴリズム自体を取り除くのは難しいです。 – user1582024

+0

私は訪問者がここでより良いアプローチかもしれないという曖昧な感覚を持っています。 – chrylis

答えて

0

他のいくつかのオプション:

  1. Fooがシングルトンである場合(すなわち、プログラム内に1つのインスタンスしか存在しない場合)、Fooにそのようなインスタンスを返す静的メソッドを持つことができます。

  2. "以前の"オブジェクトへの参照を保持し、 :

    クラスはFoo {

    Bar bar; 
    
    Foo(Bar bar) { 
        this.bar = bar; 
        bar.setFoo(this); 
    } 
    
    ResultType doFoo() { 
        ...stuff... 
        bar.doBar(); 
    } 
    

    }

    クラスバー{ フーFOO。 Baz baz;

    Bar(Baz baz) { 
        this.baz = baz; 
        baz.setBar(this); 
    } 
    
    void setFoo(Foo foo) { 
        this.foo = foo; 
    } 
    
    Foo getFoo() { 
        return foo; 
    } 
    
    ResultType doBar() { 
        ...stuff... 
        baz.doBaz(); 
    } 
    

    }

    クラスバズ{ バーバー。 Foo foo;

    Baz(Foo foo) { 
        this.foo; 
    } 
    
    void setBar(Bar bar) { 
        this.bar = bar; 
    } 
    
    ResultType doBaz() { 
        if (foo is needed) { 
         bar.getFoo().doFoo(smaller problem) 
        } else { 
         ...stuf... 
        } 
    } 
    

    }

0

あなたは個別にこれらのオブジェクトを作成し、その後お互いに登録できます。

最も単純な形式は次のようになります。

その後
class Foo { 

    Bar bar; 

    void setBar(Bar bar) { 
     this.bar = bar; 
    } 

    ResultType doFoo() { 
     ...stuff... 
     bar.doBar(); 
    } 

} 

class Bar { 

    Baz baz; 

    void setBaz(Baz baz) { 
     this.baz = baz; 
    } 

    ResultType doBar() { 
     ...stuff... 
     baz.doBaz(); 
    } 
} 

class Baz { 

    Foo foo; 

    void setFoo(Foo foo) { 
     this.foo; 
    } 

    ResultType doBaz() { 
     if (foo is needed) { 
      foo.doFoo(smaller problem) 
     } else { 
      ...stuf... 
     } 
    } 
} 

、このようなシステムの構築:あなたはより良い例外でそれを構築することができ、それをより強固にするために、次に

Foo foo = new Foo(); 
Bar bar = new Bar(); 
Baz baz = new Baz(); 
foo.setBar(bar); 
bar.setBaz(baz); 
baz.setFoo(foo); 

を必要な関連付けが行われていない場合は処理する。上記のように、これらのオブジェクトを一緒に作成するファクトリメソッドを作成して、誤って作成されないようにすることさえできます。

+1

私はBazにのみ依存するセッターを使い終わったが、それは十分だと思われる。私はコンパイル時のチェックを優先したいと思いますが、ランタイムチェックは私が推測する次善のものです。提案していただきありがとうございます。 – user1582024

関連する問題