Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flyweight and Factory problem with IDisposable

I seem to be mentally stuck in a Flyweight pattern dilemma.

First, let's say I have a disposable type DisposableFiddle and a factory FiddleFactory:

public interface DisposableFiddle : IDisposable
{
    // Implements IDisposable
}

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

Then, in my opinion, it's quite clear to the client of FiddleFactory that the factory claims no ownership of the created fiddle and that it's the client's responsibility to dispose the fiddle when done with it.

However, let's instead say that I want to share fiddles between clients by using the Flyweight pattern:

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.
    }
}

Then I feel morally obliged to make the factory itself disposable, since it creates the fiddles and keeps references to them during all of their lifetime. But that would cause problems to the clients that assumed they owned the fiddles and should therefore dispose them.

Is the problem actually that I call the factory FiddleFactory instead of, say, FiddlePool, and the "creation" method CreateFiddle instead of GetFiddle? Like this:

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
}

Then it's clearer to the client that it'll not own the returned fiddle and it's the pool's responsibility to dispose the fiddles.

Or can this only be readily solved documentation-wise?

Is there a way out of the dilemma? Is there even a dilemma? :-)

like image 673
Johann Gerell Avatar asked Feb 25 '10 17:02

Johann Gerell


2 Answers

I can see two ways out of this problem:

  • ThreadPool-style: redesign the classes so the FiddlePool provides an interface to do fiddly things. The pool doesn't hand out Fiddle instances because it has a FiddlePool.PlayFiddle method instead. Since the pool controls fiddle lifetimes, it's responsible for disposing of them.

  • SqlConnection-style: modify Fiddle's public dispose method so that it really just returns fiddles to the fiddle pool (which the fiddle class encapsulates). Internally, the fiddle pool takes care of really releasing disposable resources.

like image 88
Jeff Sternal Avatar answered Oct 11 '22 12:10

Jeff Sternal


I agree with your second opinion. The terminology 'Pool' and 'Get' do make things more clear to the consumer. However, it still does not make things clear enough, and documentation should always be added to ensure a full, valid understanding.

like image 21
jrista Avatar answered Oct 11 '22 11:10

jrista