Click here to Skip to main content
Click here to Skip to main content

The Adaptive Interface Pattern

By , 22 Oct 2012
 

Many times you read about some design pattern in a book or online, and you realise that it’s a technique you’ve been using for years – you just didn’t have a name for it. It can be a bit of a double edged sword; on the one hand it gives you a nice warm fuzzy feeling inside to know that you independently and quite naturally adopted a recognised best practice, but on the other hand you’re disappointed to learn that you haven’t actually innovated or invented something new and exciting.

What I refer to as the "Adaptive Interface Pattern" is I’m sure one of these cases. In this technique, you define a separate interface defining all of the available operations which are available for a given state of an object. In some ways it’s very similar to a state machine, but where the state transition changes the publicly exposed interface of an intersecting set of operations.

The most simple example of this would be a boolean switch. A traditional implementation might look something like this:

class BooleanSwitch
{
    private bool _isSwitchedOn = false;

    public void SwitchOn()
    {
        if (this._isSwitchedOn)
            throw new InvalidOperationException("Switch is already switched on");

        this._isSwitchedOn = true;
    }
 
   public void SwitchOff()
    {
        if (this._isSwitchedOn == false)
            throw new InvalidOperationException("Switch has not been switched on");

        this._isSwitchedOn = false;
    }
}

Clearly having both SwitchOn() and SwitchOff() methods available at the same time can easily lead to runtime exceptions. It would be better if the SwitchOn() method were only available when the object was switched off, and the SwitchOff() method only available when the object was switched on.

We can accomplish this by defining an interface for each of these states:

interface IOffSwitch
{
    IOnSwitch SwitchOn();
}

interface IOnSwitch
{
    IOffSwitch SwitchOff();
}

Our BooleanSwitch class can now be modified to implement both of these interfaces. And since calling the wrong method will now result in a compile time error, we can do away with the invalid operation exceptions…

class BooleanSwitch : IOnSwitch, IOffSwitch
{
    private bool _isSwitchedOn = false;

    public IOnSwitch SwitchOn()
    {
        this._isSwitchedOn = true;
        return this;
    }

    public IOffSwitch SwitchOff()
    {
        this._isSwitchedOn = false;
        return this;
    }

    //Finally we need to suppress the default constructor and write a factory method to create the object in its default state...
    static public IOffSwitch Create()
    {
        return new BooleanSwitch();
    }
}

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

MattDavey
Software Developer (Senior)
United Kingdom United Kingdom
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionCoolmemberYannAchard11 Nov '12 - 1:25 
I've been thinking about this approach for a while, I really like how it forces the user of a class to follow a well-defined model.
It's both a nice user guide and an compile-time check.
 
However I've never really used it because I always get the feeling that it'll get too complex too quickly: for any non-trivial case (and don't get me wrong, I think it's still very valuable for the trivial cases) I'd expect the number of interfaces will grow too fast and their interconnections (the SM graph) too complex.
I don't really see that as a limitation of the AIP technique itself, but rather of the language or the tool-set: If we could visualize it as a graph then it would make things a lot more manageable both for the user and the creator.
 
Have you encountered such scalability problems yourself?
Do you have tips on how to keep it organised?
 
Thanks
Yann
 
PS: I had a look on your blog at the Factory example that's quite neat Smile | :)
QuestionNice but how do you use it ?memberGeeko3718 Oct '12 - 5:12 
This is an original idea, I like it, really, but I can't figure out how to use it. What if you don't change the reference on IOnSwitch for a reference to IOffSwitch ? You still can switch off twice, can't you ? I feel like I would need to move the state machine on the client classes with this pattern. What about mulithreading ? What about having many objects referencing the BooleanSwitch as an IOffSwitch, and one of them calls SwitchOn() ? Could you provide a sample of how you use this pattern ?
Thanks in advance.
AnswerRe: Nice but how do you use it ?memberMattDavey22 Oct '12 - 0:23 
Hi there, I have a follow up article to this which gives one possible usage scenario.
QuestionI am sorrymemberQwertie16 Oct '12 - 5:58 
I meant to click on this web page and it looks like I accidentally filed a "report" against it. I moved my mouse down and clicked the first paragraph, but a menu appeared a split-second before that and then it tells me I've reported the article. Stupid UI doesn't offer any way to cancel, and it doesn't even say which of the 11 reports I made!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 22 Oct 2012
Article Copyright 2012 by MattDavey
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid