Context driven Fluent interfaces via Chameleon pattern
Before anyone flames me with bad comments, let me do a little disclaimer:
- I am not a pattern authority; there is a big chance that this already exists under a different pattern. If so, please let me know and I will start using the original name instead of mine.
- I am calling it by name so that in future I can easily refer to the beast by name and not be ambiguous about it.
So… let the interface extravaganza begin…
So you want to make a Fluent interface in c#, right? You want your interface to bend and shape itself depending on the how it’s used, right?
A little example; I was lately building my own Repository implementation for NHibernate and for the Find part, I want to build it as a fluent interface instead of having a parameter explosion smell.
I want to be able to do something like:
Repository.Find(when.Customer.Name == “Vladan”)
.Order(on.Customer.Id)
.StartFrom(10)
.LimitTo(20)
.All();
Let’s dissect requirements for each of the methods (this is only a subset of requirements I’ve put in front of myself when defining this interface)
- Find should be able to chain to Order, StartFrom and All
- Order should be able to chain StartFrom and All
- StartFrom should be able to chain only LimitTo
- LimitTo should be able to chain Order and All
Besides the specified allowed chain, the methods should not allow calls to other methods in the chain (e.g. “StartFrom” should not be allowed to call “All” directly, or “Order” should not be able to chain “LimitTo” directly) – or in other words, our method calls should be presented to us depending on the context of their usage, ok?
How do we implement this? Well, let’s start by defining for each method call above an interface:
public interface IFindQuery
{
}
public interface IFind
{
}
public interface IOrder
{
}
public interface IStartFrom
{
}
public interface ILimitTo
{
}
Now let’s chain them together depending on the allowed chaining requirements:
public interface IFindQuery
{
IFind Find(…);
}
public interface IFind
{
IOrder Order(…);
IStartFrom StartFrom(…);
List<OfResult> All();
}
public interface IOrder
{
IStartFrom StartFrom(…);
List<OfResult> All();
}
public interface IStartFrom
{
ILimitTo LimitTo(…);
}
public interface ILimitTo
{
List<OfResult> All();
}
Still with me?
Now, can you see that we’ve defined the context of chaining these methods? By being explicit about it, we were able to limit the context only to those operations we want to allow in a given moment.
How do we implement this?
Well the great thing is that now I can implement the complete Find part of my repository as a single object that implements all these interfaces and acts as a Chameleon – or better said, that changes its (inter)face depending on the situation.
Let’s try it:
public class FindQueryImpl : IFindQuery,
IFind,
IOrder,
IStartFrom,
ILimitTo
{
public IFind Find(…)
{
…do something with it…
return this;
}
IOrder Order(…);
{
…do something with it…
return this;
}
IStartFrom StartFrom(…);
{
…do something with it…
return this;
}
ILimitTo LimitTo(…);
{
…do something with it…
return this;
}
List<OfResult> All()
{
…do something with it…
return some_result;
}
}
As you can see, by always returning a self reference, only under a different (inter)face we become context driven with a really simple object graph to support it.
And that ladies and gents… makes our chameleon. One object which shows it’s (inter)face based on context.
One thing to note though… this object would probably in very complex scenarios become too big and complex to maintain, so in those cases you should probably try to take it to the next level by partiotioning the chameleon to several smaller ones.
What do you think?

Leave a Reply