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? :-)
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With