2009-06-08 34 views
9

在通常的策略模式中,我們將每個策略都視爲一個類。我們不能讓它成爲一個函數,只是在我們實例化一個對象時將該引用賦值給該函數,並讓該對象調用該函數?在戰略模式中,我們不能把每個戰略作爲一個功能,而不是一個階級?

+0

在這種情況下與Java玩得開心:) – Joey 2009-06-08 09:38:15

+1

爲什麼? Java不支持對函數的引用? – 2009-06-08 09:42:40

+7

+1用於批判性地思考設計模式。我會說許多設計模式源於語言無能的根源。所以在許多情況下,設計模式不是聖經:) – kizzx2 2009-06-08 09:45:02

回答

3

在最簡單的情況下,您可以用函數指針替換策略模式。然而,考慮這種情況下

class HourlyPayStrategy implements PayStrategy 
{ 
    public int calculate() 
    { 
     int x = doComplexOperation1(); 
     int y = doComplexOperation2(); 

     return x + y; 
    } 

    private int doComplexOperation1() 
    { 
     // ... 
    } 

    private int doComplexOperation2() 
    { 
     // ... 
    } 
} 

如果我們只是做了簡單的函數指針,事情開始變得非常毛茸茸的,因爲你不能再重構那個東西(當然,至少不是一個很好的方式封裝)。

+0

我不同意這一點。無論是引用HourlyPayStrategy還是HourlyPayStrategy.calculate,在重構或封裝方面都沒有什麼不同。 – 2013-05-23 14:12:12

+0

@DavidArno用你的符號我相信你熟悉C#,它在執行_eta expansion_方面做得很好。這種表示法在許多語言中並不容易實現:JavaScript,Ruby,Python,Java,OCaml甚至(從幾年前的內存中講),C++(問題:C++ 11如何與現今相媲美?)。 – kizzx2 2013-05-23 17:25:39

+0

在許多語言中,當需要_function_作爲參數時,它與期望_method_完全不同,在這種情況下編譯器/運行時需要隨附關聯對象。那麼是的,對於C#你的論點有腿。 – kizzx2 2013-05-23 17:28:16

4

取決於語言。在C#中,你可以讓它成爲一個委託。在Java中,它寧願成爲一個匿名類。在C++中,你可以真正把它變成一個函數指針。

2

當然,雖然通過使用對象,你可以利用繼承的方式,你不能只用函數。

1

在C#中,您可以使用具有策略模式的委託。例如,請看這個 blog post

1

在大多數C++實現中,下面發生了什麼幾乎是你的建議。編譯器通常可以解決通話Strategy.virtualMethod()這樣的(僞代碼):

 
    (Strategy.pVtable[indexOfVirtualMethod])() 

所以,如果你只關注一個指針(pVtable)你應該先配置文件的一個間接引用多,如果你能不能找出更嚴重的熱點。

我的感覺是,當您使用函數指針而不是策略對象時,您的代碼將難以理解和維護。