Saving Memory and the Strategy Pattern

As might be seen from the previous two posts, memory management is a bit of a hot issue at the moment. Before going round clearing up big objects, it may be worthwhile looking at savings that can be made elsewhere. The Singleton pattern is a useful way of making an object once and once only and then reusing it.

There is a warning. If you use the Singleton pattern, then the object stays around in memory forever. This may be worse than recreating the object occasionally. However, if it’s a small object, then the overhead of keeping it is probably lower than the overhead of constructing and collecting loads of temporary ones.

In .NET and Java you frequently need to create a mini object to satisfy an interface where the object has no state, but just has a specific version of the algorithm the interface needs. This is, effectively, the strategy pattern.

.NET even helps us with this by providing delegates.

Ashley Definition Time: A delegate is a single function interface which is realised by the CLR for you, rather than having to be realised by writing a class.

The strategy pattern often looks like this:

public static IMyStrategy GetStrategyFor(string classification)
{
  if (classification.Equals(Thing1))
  {
    return new Strategy1();
  }
  else
  {
    return new GenericStrategy();
  }
}

Once we have our strategy object, we either store it or pass it around. Generally, this strategy has no internal state. So making a new one is really just a way to cope with the fact that it can’t be used statically as it’s being used via interface.

I would prefer, in this situation, to make each implementation of IMyStrategy implement the singleton pattern. Then there will only ever be at most one of each of these objects in memory, though over time it will become exactly one.

// probably hidden and in the same package as the code which converts some input
// into the strategy object to use
internal class Strategy1 : IMyStrategy
{
   // singleton instance - evaluated when first needed
   private static Strategy1 instance = new Strategy1();

   // hide the constructor to avoid people making spare ones
   private Strategy1() {}

   // provide instance getter for Singleton access
   public Strategy1 Instance { get { return instance; } }

   // implementation of IMyStrategy follows
}

Calling code would be:

public static IMyStrategy GetStrategyFor(string classification)
{
  if (classification.Equals(Thing1))
  {
    return Strategy1.Instance;
  }
  else
  {
    return GenericStrategy.Instance;
  }
}

Overall, this reduces the number of silly little objects cluttering up the place.

Advertisements

9 comments

  1. Nice article, but from myPOV the “StrategyDispatcher” should decide, if there is the need to create for each object a new instance or not… for example if the strategy “changes” from a stateless small object to a statefull big one, the garbage collector has no chance to get rid of the memory.

  2. The repobsibility, if there is only one instance or many for a strategy should be on the “StrategyCreator” …. also with this implementation, you must take care of the “memory”, when the small stateless strategies must switch to big statefulls ….

  3. Hi JJ

    RE comment #1 – the last code segment was the internals of the StrategyDispatcher as you call it. Completely agree.

    RE comment #2 – also agree, it’s the internals of the StrategyDispatcher – or perhaps StrategyLookup or StrategySelector. Actually getting the right strategy might be the subject of a Facade pattern.

    As for memory management of small stateless vs large stateful strategy objects, there’s a big question. Should strategy objects have state? See the next post!

  4. Interesting stuff there. A few warnings, though.

    1. Generic implementations of design patterns can sometimes complicate the design, as they provide only a framework, which you have to correctly insert your implementation into… and design patterns often don’t need much framework to exist, so you end up with more code and less understanding.

    2. The implementation of a generic strategy selector, based on an enum is not adding a huge amount that Dictionary doesn’t already provide.

    3. Delaying instantiation of your strategy objects seems to be overkill. They are almost zero-memory in size and probably take no major megaFLOPS to create. If necessary, there’s always the C# class Lazy

    http://msdn.microsoft.com/en-us/library/dd642331.aspx

    4. The enum is not necessarily the way you would naturally choose a strategy. However, it MIGHT be if you are also using the memento pattern, where the serializable/deserializable enum is the “memento” passed back from the object to refer to a particular type of thing.

    That said, there is a use for code like the above in some programs that have a lot of strategies chosen programmatically from enums.

  5. @1 -> yes
    @2 -> yes
    @3 -> Not sure, if it works, because in this case is an Interface …..
    @4 -> yes, normally I would choose just an string, but I was interested in the way if the “Base Class” Enum works 😉

  6. Even, the Lazy is not needed in the implementation of the StrategySelector, I tried to wave it into the code…
    Therefore I changed the _singletonControl to ->
    private readonly Dictionary<Enum, Lazy> _singletonControl = new Dictionary<Enum, Lazy>();

    To have the ability todo something like this in the RegisterStrategy method ->
    if (instanceType == InstanceType.Singelton) {
    Type generic = typeof (Lazy);
    Type specific = generic.MakeGenericType(strategy);
    ConstructorInfo ci = specific.GetConstructor(Type.EmptyTypes);
    object o = ci.Invoke(new object[] {});
    _singletonControl[value] = (Lazy)o;
    }

    The Compiler has no problems, but at runtime a error is thrown ….

    The only idea, I have in the moment is to use a base class for the strategies instead of an interface…

    Any other ideas, that works with an interface?

    It is just a “finger excersise 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s