What is the difference between NVI ( Non-Virtual Interface ) and the Template Method patterns?
They seem very similar and I've read both that they're basically the same and that they're subtly different with Template being somehow more general.
But, the key difference is that Strategy Pattern is about modifying a behaviour of a context in runtime using strategies, while Template Method Pattern is about following a skeleton implementation of an algorithm and modifying its behaviour by overriding methods of the skeleton class in the subclasses.
Strategy is more in line with the dependency inversion principle of the SOLID principles of coding. Whereas, Template pattern may give you a simpler design which is also an important factor while making a choice between the two.
Template method design pattern is to define an algorithm as a skeleton of operations and leave the details to be implemented by the child classes. The overall structure and sequence of the algorithm are preserved by the parent class. Template means Preset format like HTML templates which has a fixed preset format.
The intent of the template method is to define the overall structure of the operation, while allowing subclasses to refine, or redefine, certain steps.
NVI is an idiom, Template Method is a pattern. NVI is an implementation of the Template Method Pattern using dynamic dispatch in C++; it is also possible to create template methods in C++ using template metaprogramming to eliminate the dynamic dispatch.
A pattern is more general than an idiom, and languages may use different idioms to implement the pattern.
As has been said, NVI is a progamming idiom, related to a category of languages. It's been promoted by Herb Sutter among others, because it helps enforcing contracts:
However, the implementation may actually differ considerably, for example another example of NVI implementation is to combine it with Pimpl:
class FooImpl;
class Foo
{
public:
enum type { Type1, Type2 };
Foo(type t, int i, int j);
int GetResult() const;
private:
FooImpl* mImpl;
};
And for the implementation:
struct FooImpl
{
virtual ~FooImpl();
virtual int GetResult() const;
};
class FooType1: public FooImpl
{
public:
FooType1(int i, int j);
virtual int GetResult() const;
private:
/// ...
};
I've always found that it conveyed the point better. Have you figured it out ?
The main point is that virtual
is an implementation detail. And exposing implementation details in the interface is a bad idea, because you may wish to change them.
Furthermore implementation details tend to mess with binary compatibility. For example adding a new virtual
method in a class may change the layout of the virtual table (common implementation technic) and thus botch the binary compatibility. On gcc you need to make sure that you add it last (among the virtual) if you wish to preserve the compatibility.
By using the NVI + Pimpl combination above, there is no virtual
at all (not even private) in the class exposed. The memory layout is backward and forward compatible. We have achieve binary compatibility.
Here, we use several patterns at once:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With