The patterns book is 15 years old, that’s about 150 in developer years. All told, it’s amazing that more of the patterns aren’t out of date. Here are some that I think could be safely retired. Again, they’re not necessarily bad ideas, it’s just that they’re special cases of more general principles, and I favour understanding the principles.
I’ll be honest, I’m not sure I get the point of the Bridge pattern. A bridge is exemplified by the following example from finance:
- You have an interface for a traded instrument. Call it IInstrument.
- Shares are one of the simplest kinds of instrument. We extend the interface to IEquity.
- We provide a base implementation of Instruments that developers can inherit from. We call this InstrumentBase.
- We implement shares using the concrete class Equity which inherits from InstrumentBase.
In this case, we could modify the IInstrument interface. This would affect the InstrumentBase classes, but not the Equity class. Equally, we could modify the implementation of Instrument without modifying the external interfaces.
Now, I have a problem with all of this. Basically, as far as I can tell, the Bridge pattern is what I call object-orientated development. There’s two components of the pattern:
- The use of interfaces to shield implementations from the consumers. This is the Open/Closed principle.
- The use of inheritance to specialize. This is also known as coding in C#.
In short, Bridge doesn’t say anything other than “built according to good design principles”.
Template and Strategy
Template patterns are the same as Bridge patterns, only the emphasis is different. Rather than specializing an entity, you’re specializing an algorithm. Now, the interesting thing here is: there’s two ways to create a general algorithm with specialization.
- Inheritance (which the Template pattern requires)
- Composition (in which case you call it a Strategy pattern)
Typically, I’d favour the latter, as would Gamma et al.
Usually, in C#, you can generalize an algorithm just by passing in a function. For instance, consider the following code:
gofPatterns.FirstOrDefault(pattern => pattern.Name == “Template”)
FirstOrDefault is a parameterized algorithm. The expression ” pattern => pattern.Name == “Template” ” specializes it. Implementing the same algorithm through inheritance would just be plain painful. In short, Bridge and Template are both names for specific cases of more general problems, and the specialization isn’t useful. So, I wouldn’t really recommend using the terminology. That’s not to say that you won’t use the pattern, just that you’ll probably not help anyone by telling them you used a template pattern when you did so.
In practice, I have been known to use the term “Strategy Pattern”, but usually I just mean “I outsourced some decision making”. In general I think you’re better off just understanding that there are multiple ways of parameterizing an algorithm.
Basically, a flyweight object is a representation of an entity which strips out most of the information and just keeps the truly vital information. This is done for memory conservation. I’m including this under “obvious” because it will have occurred to anyone who has run into the problem it solves (and because I can’t think of a better place to put it). You could also describe this as a “reference” pattern, since often the flyweight objects contain just enough information to find the true entity in a database if needed.
An interesting case is lazy loading in NHibernate. NHibernate generates proxy objects which are themselves initially flyweight, but become heavyweight on their first access.
Again, I don’t think this is particularly useful terminology. In the time since Design Patterns was written, the whole idea of a “true” object representation has declined in importance. Finely-grained interfaces customized by consumer, pervasive proxying, presentation models are all part of a general principle that objects matter at point of use. The world has moved on.
Bridge, Template and Strategy are also obvious patterns, but unlike Facade, Builder and Adapter, aren’t really useful for communication.
- In the case of Bridge, typically just saying that you’ve a) hidden something behind an interface or b) used inheritance to specialize is more clear.
- In the case of Template or Strategy, it’s better to refer to what you’re doing as a parameterized algorithm, irrespective of the form that parameterization takes.
- “Strategy Pattern” is nonetheless a popular term, and I’m not advocating getting into a terminology war with something who wants to call what they’re doing a strategy pattern. But you might wish to introduce them to Erlang sometime…
The Flyweight pattern is part of a general principle that objects can have more than one representation. I wouldn’t personally use the term.