我似乎在精神上陷入了享元模式的困境。

首先,假设我有一个一次性类型 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, ,以及“创造”方法 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
}

然后,客户端会更清楚地知道,它不会拥有返回的小提琴,并且池有责任处置这些小提琴。

或者这只能通过文档来轻松解决?

有没有办法摆脱困境呢?甚至还有困境吗?:-)

有帮助吗?

解决方案

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

  • 线程池式: :重新设计课程,以便 FiddlePool 提供一个接口来完成一些繁琐的事情。泳池不派发 Fiddle 实例,因为它有一个 FiddlePool.PlayFiddle 方法代替。由于池控制小提琴的生命周期,因此它负责处置它们。

  • SqlConnection风格: :调整 Fiddle的公共 dispose 方法,以便它实际上只是将小提琴返回到小提琴池(小提琴类封装的)。在内部,小提琴池负责 真的 释放可支配资源。

其他提示

我同意你的意见。术语“池”和“GET”做让事情更清楚给消费者。但是,它仍然没有把事情说清楚就够了,应该经常补充文件,以确保一个完整的,有效的理解。

您应该做些更不仅仅是文档和命名方法来告诉客户不要丢弃调用。真的会更好,以便客户调用Dispose所以请的使用模式。花一些方向,从我们的数据库连接池构建的。

在数据库池一串的连接,它本身池感知的。调用代码创建一个连接,打开它,并在其上调用close(处置)。调用代码并不真正了解它是否合并与否,这一切都通过内部连接类处理。随着入池连接,调用open()如果连接已经打开被忽略。关闭()/处置()被调用,并在池连接的情况下,这实际上返回的连接返回到池中,而不是关闭它的。

您可以通过创建一个PooledFiddle类重写处置和对象返回池中做同样的事情。理想情况下,客户端甚至不必知道它是一个汇集小提琴。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top