1

Let's say I have an interface for the Command pattern with undo functionality:

interface ICommand
{
    void Execute();
    void Undo();
}

This comes with a contract. Basically the command can be in one of two states - either it has been executed or not, and that determines the only method that can be called.

To add a check for this, I could create an abstract class called SafeCommand or simply CommandBase with this protection:

abstract class CommandBase : ICommand
{
    private bool executed = false;

    public void Execute()
    {
        if (executed)
            throw new InvalidOperationException();

        ExecuteImpl();
        executed = true;
    }

    public void Undo()
    {
        if (!executed)
            throw new InvalidOperationException();

        UndoImpl();
        executed = false;
    }

    protected abstract void ExecuteImpl();
    protected abstract void UndoImpl();
}

When I want to implement the actual command functionality, I now have to override the ExecuteImpl and UndoImpl methods instead.

Another way to solve this could be to make the methods virtual, but I prefer this way because I can't forget to implement the methods and also can't omit the base call. Also, in other cases where I need to have some code before and after the call, this will be the only solution.

I first encountered this pattern in WPF, where it's actually used twice in the same inheritance hierarchy with UIElement Measure, virtual MeasureCore and FrameworkElement override MeasureCore and virtual MeasureOverride methods.

My question is, is there a name for this pattern? It seems to me like some sort of a (forced) Adapter using inheritance instead of composition.

8
  • I think the more interesting question than asking for a name is, if this approach violates some of the SOLID principles or the principle of least astonishment. I think it does not, but lets see how others think about it.
    – Doc Brown
    Commented Dec 29, 2017 at 12:08
  • One thing that I would change name to UndoableCommand instead of CommandBase.
    – Euphoric
    Commented Dec 29, 2017 at 12:24
  • @Euphoric: but then why no change to the interface name IUndoableCommand?
    – Doc Brown
    Commented Dec 29, 2017 at 12:25
  • I'm not sure if it makes sense to have an IUndoableCommand that would derive from ICommand since it seems to me like ICommand doesn't have this limitation and could be called multiple times. That's also an interesting question.
    – Neme
    Commented Dec 29, 2017 at 12:27
  • That too. Because at first I confused it with standard ICommand.
    – Euphoric
    Commented Dec 29, 2017 at 12:29

1 Answer 1

0

The only real GOF pattern here I can see in this construct is the "template method pattern".

The public interface of any CommandBase derivation - as seen from any code outside the class hierarchy - does not change, so I don't see this as

"providing a different interface to the subclasses",

as your question title imposes. My interpretation of this is more "providing an easier way to implement the interface with error checking".

The more interesting question here is: is there a LSP violation? I think not, if the contract is written down exactly as stated in the question, with the additional remark that Execute and Undo will throw exceptions when called in wrong order. Then the template method pattern will actually help to ensure the contract.

5
  • By different interface I didn't mean a different public interface but a different interface (even though in this case it's just a different name for the methods) from the point of view of the subclass to implement. That's why saw a similarity to an adapter. Here the interface has exactly the same semantics and contract but in other cases this might not be the case and the base class might be adding some additional logic/calculations as I saw in WPF where in one case it does something else with the return value of the template method and doesn't actually return it publicly.
    – Neme
    Commented Dec 29, 2017 at 12:38
  • And with FrameworkElement it actually returns different sizes, adding margin for example.
    – Neme
    Commented Dec 29, 2017 at 12:40
  • I wasn't actually familar with the template method pattern, but reading about it now seems to me like it's just another word for abstract methods - I can't see a scenario where I would use them without it being a "template" method. Isn't that what the word abstract already means?
    – Neme
    Commented Dec 29, 2017 at 12:49
  • @Neme: the "template method pattern" is not another word for abstract methods, but it is actually the use case for abstract or virtual methods. And sure, I understand exactly what you meant by "interface from the point of view of the subclasses". However, the new "interface" (which is not an interface in the sense of the language element "interface" any more) does not have "exactly the same semantics and contract", it has a weaker contract (since there is no requirement for throwing exceptions any more).
    – Doc Brown
    Commented Dec 30, 2017 at 0:18
  • ... and the fact that for this case the methods ExecuteImpl and UndoImpl look symmetric to Execute and Undo is IMHO to some degree a coincidence. You next version of CommandBase might require additional or different abstract methods to be implemented, that would not change the overall structure.
    – Doc Brown
    Commented Dec 30, 2017 at 0:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.