Building a CachedRepository via Strategy Pattern

In part one of this series, I introduced the CachedRepository pattern, and demonstrated how it can be applied through the use of simple inheritance to an existing Repository class.  This allows us to easily configure whether or not we want to use caching at the repository level through the use of an IOC Container like StructureMap. However, using inheritance to achieve the behavior isn’t always desirable, since generally it’s better to use object composition if possible (this tends to result in more flexible designs).

One benefit of the inheritance-based approach is its simplicity. Both in terms of the code require and in terms of wiring up the interfaces and implementations in the IOC container. You end up with something like this in your StructureMap Initialize() method:

Switching between the two is trivial and the behavior is very clear.

Now, to implement the same strategy using the Strategy Pattern, only a few minor changes are required. First, the CachedRepository class needs to be modified to no longer inherit from EfAlbumRepository, but rather to simply implement IAlbumRepository.  Next, it needs to take in an IAlbumRepository in its constructor and assign it to a local instance.  Finally, the GetTopSellingAlbums() method needs modified to no longer specify the override keyword, and to call _albumRepository rather than base.  The modified version is shown below (the original is in the first CacheRepository article):

With the new class in place, we need to adjust how we configure its use in our IOC container’s initialize method.  The code required to avoid the cache remains the same, but the code to set up the correct creation of the CachedRepository object is slightly more involved, as we must now specify the type to provide to the constructor.  The result is shown here:

This approach requires some more advanced features from the IOC container.  In many systems, access to the IOC container is abstracted away behind a common interface, with simple methods like Register<T> and Resolve<T>, and probably not many overloads for things like specifying constructor parameters.  In such setups, the inheritance-based approach will most likely be the simplest one to follow, since it is amenable to this kind of simplistic type resolution.  However, if you have access to your IOC container’s more advanced methods, and it supports this kind of resolution specification (as StructureMap does), then the strategy pattern based approach may offer more flexibility.

Thanks to Kyle Malloy on the StructureMap Users mailing list for his assistance with the SM syntax required for this case.

  • Introducing the CachedRepository Pattern : Steve Smith’s Blog

    Pingback from Introducing the CachedRepository Pattern : Steve Smith’s Blog

  • David L. Penton

    This IoC pattern is exactly what I am doing for clients these days. It works great.

  • Twitter Trackbacks for Building a CachedRepository via Strategy Pattern [stevesmithblog.com] on Topsy.com

    Pingback from Twitter Trackbacks for Building a CachedRepository via Strategy Pattern [stevesmithblog.com] on Topsy.com

  • Kyle Malloy

    Another interesting way to configure this would be using Profiles. They would ease the burden of switching to your cached repositories as the number of repositories increases. Also another cool side effect is that you could write an ActionFilterAttribute that switches the profile back to the default to isolate specific actions to use the non cached versions.

    ObjectFactory.Initialize(x =>

    {

    x.Scan(scan =>

    {

    scan.TheCallingAssembly();

    scan.WithDefaultConventions();

    });

    x.For<IAlbumRepository()

    .Use<EfAlbumRepository>();

    x.Profile("Cached", p =>

    {

    p.For<IAlbumRepository()

    .Use<CachedAlbumRepository>()

    .Ctor<IAlbumRepository>()

    .Is<EfAlbumRepository>();

    });

    });

    ObjectFactory.Profile = "Cached";

  • Neal Blomfield

    Your approach above is not an implementation of the strategy pattern, rather you have taken the (correct) step of implementing a decorator through composition rather than inheritance (as you did in the previous example).

    I would also suggest the use of EnrichWith when registering decorators in structuremap.

  • ssmith

    @Neal,

    Thanks, I’ll have to check out EnrichWith, as I have not used it before. Whether caching in this fashion is using Decorator or Proxy pattern, for instance, is I think a matter of some debate, and certainly in either case it could be achieved via inheritance or composition. Inheritance is certainly the more textbook approach. I tend to see "injecting how something is done via the constructor" as the heart of the strategy pattern’s intent, and certainly just looking at the class structure involved in the above solution, it strongly resembles Strategy to me, but I can see how that is perhaps the less important pattern to call attention to than the Proxy/Decorator usage.

    Thanks much for your comment!

  • Kyle Malloy

    @Neal,

    From my experience when configuring decorators EnrichWith provides an inflexible solution. I recommend directly configuring the dependency chain for the specific scenario in this blog post because more dependencies can be added to CachedAlbumRepository at no cost to the configuration. I reserve EnrichWith when configuring dynamic proxies.

  • JD

    Thanks for this article, I’m trying to add a caching layer to the http://efmvc.codeplex.com/ demo project… For any other newbs out there who were confused about the "lock" like me, this explains what that code block is doing: stackoverflow.com/…/what-is-the-bes

    So much to learn… thanks for posting this!

  • Glav

    This could also be further augmented with this http://bit.ly/nhmUCn to use a caching interface
    (ICacheProvider) to include in your DI registration and has support for
    memcached, Azure AppFabric, Http runtime cache and std memory (via
    config).