IDisposable的Flyweight和Factory问题

时间:2010-02-25 17:34:24

标签: c# idisposable factory-pattern flyweight-pattern

我似乎在精神上处于Flyweight模式困境中。

首先,假设我有一次性类型DisposableFiddle和工厂FiddleFactory

public interface DisposableFiddle : IDisposable
{
    // Implements IDisposable
}

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

然后,在我看来,FiddleFactory的客户很清楚,工厂声称没有创建小提琴的所有权,并且在完成操作时,客户有责任处置小提琴。

但是,让我们说我想通过使用Flyweight模式在客户端之间分享小提琴:

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,而“创建”方法CreateFiddle而不是GetFiddle?像这样:

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
}

然后对客户来说更清楚的是它不会拥有返回的小提琴,并且游泳池有责任处理小提琴。

或者这只能在文档方面轻松解决吗?

有没有摆脱困境的方法?甚至有两难吗? : - )

3 个答案:

答案 0 :(得分:7)

我可以看到解决这个问题的两种方法:

  • ThreadPool风格:重新设计类,以便FiddlePool提供一个界面来做繁琐的事情。该池不会分发Fiddle个实例,因为它具有FiddlePool.PlayFiddle方法。由于游泳池控制着生命周期,因此它负责处理它们。

  • SqlConnection-style :修改Fiddle的公共配置方法,以便它真正只是将小提琴返回到小提琴池(小提琴类封装)。在内部,小提琴池负责真正释放可支配资源。

答案 1 :(得分:2)

我同意你的第二意见。术语“池”和“获取”确实使消费者更清楚。但是,它仍然没有说清楚,并且应该始终添加文档以确保完整,有效的理解。

答案 2 :(得分:1)

您应该做的不仅仅是文档和命名方法,以告诉客户不要调用dispose。真的,最好让客户端调用dispose,以便使用该模式。从我们的数据库连接池中建立一些方向。

数据库汇集了一堆本身可以识别池的连接。调用代码会创建一个连接,打开它,并在其上调用close(dispose)。调用代码甚至不知道它是否合并,它都是由连接类在内部处理的。使用池连接,如果连接已打开,则忽略调用Open()。调用Close()/ Dispose(),并且在池连接的情况下,这实际上会将连接返回到池而不是关闭它。

您可以通过创建一个PooledFiddle类来执行相同的操作,该类重写Dispose并将对象返回到池中。理想情况下,客户甚至不必知道它是一个汇集的小提琴。