2010-02-25 53 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