2016-12-30 23 views
1

假設我有一個直觀的問題,使用遞歸最好解決。如何避免將一個上下文傳遞給一堆方法調用?

我也想使用依賴注入使代碼testeable:現在

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... 
     } 
    } 
} 

,如果巴茲wan't依賴於富,你可能只是這樣做:

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

Baz可以帶任何Foo,所以如果它只是得到頂端的那個就沒有問題,從而形成一個循環。

(JVM可以負責循環IIRC)。只有Baz可以確定它是否需要Foo。

以可測試的方式讓Foo進入Baz的最簡潔方法是什麼?

是否將Foo參數添加到我的唯一選項doBaz()? (言下之意是美孚需要通過「本」,以doBar,然後把它傳遞給doBaz,等...或者是有更好的辦法?)

編輯:

也許問題的描述的確會有用。

該算法基本上是一個編譯器,它將代碼作爲輸入並輸出代表代碼含義的數據結構。這種數據結構本質上是高度遞歸的。

但是,代碼中可能存在不清晰(認爲未聲明的方法)。造成這個問題的原因是,與大多數編譯器不同,這不應該簡單地在用戶身上嘔吐一堆錯誤,而是向用戶提供一個選項來輸入更多的代碼。

基本上,編譯器會暫時停止編譯「主」代碼,並開始編譯這個由用戶提供的新代碼。在此之後,它會將產生的數據結構附加到「主」數據結構。

如果在用戶提供的這個代碼中有更多的非文字,它將再次允許用戶澄清。

基本上,實現代碼不完整的組件(由Baz代表)必須調用「main」組件(Foo)來開始編譯用戶提供的代碼。

+0

如果您更詳細地描述實際問題,這可能會有幫助。很可能有一種不同的分解方式會減少週期性。 – chrylis

+0

好的,完成了。只是這個過程本身是以用戶可見的方式遞歸的,所以也許很難擺脫遞歸算法本身。 – user1582024

+0

我有一種模糊的觀點,認爲訪客可能是更好的方法。 – chrylis

回答

0

一些其他選項:

  1. 如果Foo是單(即在程序中只有一個實例),那麼你可以在Foo中有一個靜態方法返回這樣的實例

  2. 你可以保留對「前一個」對象的引用,並使用它從Baz中遍歷回來:

    類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

你可以seperately構建這些對象,然後海誓山盟登記。

最簡單的形式是這樣的:

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上使用了依賴的setter,但事實證明這似乎足夠了。我寧願編譯時檢查,但運行時檢查是我猜的下一個最好的事情。感謝您的建議。 – user1582024

相關問題