2010-02-25 31 views
11

我似乎精神卡在輕量級模式的困境。輕量級和工廠問題與IDisposable

首先,讓我們說我有一個一次性的類型DisposableFiddle和工廠FiddleFactory

public interface DisposableFiddle : IDisposable 
{ 
    // Implements IDisposable 
} 

public class FiddleFactory 
{ 
    public DisposableFiddle CreateFiddle(SomethingThatDifferentiatesFiddles s) 
    { 
     // returns a newly created fiddle. 
    } 
} 

然後,在我看來,這是很清楚的FiddleFactory客戶端,該工廠聲稱沒有創建的小提琴的所有權而且在處理小提琴時,客戶有責任處理小提琴。

然而,我們不是說我想要通過使用享元模式共享客戶端之間小提琴:

public class FiddleFactory 
{ 
    private Dictionary<SomethingThatDifferentiatesFiddles, DisposableFiddle> fiddles = new ...;   

    public DisposableFiddle CreateFiddle(SomethingThatDifferentiatesFiddles s) 
    { 
     // returns an existing fiddle if a corresponding s is found, 
     // or a newly created fiddle, after adding it to the dictionary, 
     // if no corresponding s is found. 
    } 
} 

然後,我覺得在道義上有義務使工廠本身一次性的,因爲它創建了小提琴,並保持引用給他們一生的一切。但是,如果客戶認爲他們擁有小提琴,那麼這會給客戶帶來問題,因此應該處理他們。

實際上是問題,我稱之爲工廠FiddleFactory而是說:FiddlePool,並「創造」的方法,而不是CreateFiddleGetFiddle?就像這樣:

public class FiddlePool : IDisposable 
{ 
    private Dictionary<SomethingThatDifferentiatesFiddles, DisposableFiddle> fiddles = new ...;   

    public DisposableFiddle GetFiddle(SomethingThatDifferentiatesFiddles s) 
    { 
     // returns an existing fiddle if a corresponding s is found, 
     // or a newly created fiddle, after adding it to the dictionary, 
     // if no corresponding s is found. 
    } 

    // Implements IDisposable 
} 

然後它更清晰的客戶端,它會不會自己返回的小提琴,這是池的責任處置小提琴。

或者只能通過文檔方式解決這個問題嗎?

有沒有辦法走出困境?還有什麼困難嗎? :-)

回答

7

我可以看到兩種方式出這個問題:

  • 線程池式:重新設計的類,因此FiddlePool提供的接口做繁瑣的事情。池不會發出Fiddle實例,因爲它有一個FiddlePool.PlayFiddle方法。由於池控制小提琴的生命週期,它負責處理它們。

  • SqlConnection的風格:修改Fiddle的公共Dispose方法,以便它真的只是返回小提琴的小提琴池(其中小提琴類封裝)。在內部,小提琴游泳池照顧真的釋放一次性資源。

+0

謝謝,第一個更好地遵循Demeter法則,第二個更適合我的整體設計。嗯... – 2010-02-25 22:18:36

+0

我會把我的兩分錢的第一種方法 - 我見過有太多人嘗試編寫自己的SqlConnnection池! (不是真的,但我*有必須解釋爲什麼沒有必要。) – 2010-02-26 15:52:32

2

我同意你的第二個意見。術語'Pool'和'Get'的確讓消費者更清楚。但是,它仍然不夠清楚,並且應始終添加文檔以確保完整,有效的理解。

+3

我的想法確切。此外,我可能不會叫你的類DisposableFiddle,除非你想讓用戶Dispose()它... – 2010-02-25 17:45:15

+0

@Reed:同意DisposableFiddle。適當的命名對於傳達意圖至關重要,是防止錯誤使用的第一道防線。 – jrista 2010-02-25 21:07:31

+0

嘿,是的,我只是預設了一次性使用示例名稱,以便在我的(困惑)步驟中更容易地遵循... – 2010-02-25 22:13:15

1

您應該做的不僅僅是文檔和命名方法,以告訴客戶不要調用dispose。真的有客戶打電話處理會更好,因此使用模式。從我們的數據庫連接池中建立一些方向。

數據庫會聚集一堆本身具有池感知的連接。調用代碼創建一個連接,打開它並調用close(dispose)。調用代碼甚至不知道它是否合併,它都是由連接類內部處理的。對於連接池,如果連接已打開,則調用Open()將被忽略。關閉()/ Dispose()被調用,並且在池連接的情況下,這實際上將連接返回到池而不是關閉它。

您可以通過創建一個覆蓋Dispose並將對象返回到池中的PooledFiddle類來執行相同的操作。理想情況下,客戶甚至不必知道它是一個集合的小提琴。

+0

「理想情況下,客戶甚至不必知道它是一個集合的小提琴。」 - 是的,我同意這一點。我認爲這是一個隱藏起來更好的實現細節。 – 2010-02-25 22:16:16