#The strategy pattern is really bad.html
For clarity, I would first like to state that I'm specifically referring to what OOP
depicts as THE strategy pattern. If we restrict our selves to the definition of
"behaviour as data", procedural function pointers and much of functional programming
becomes examples to the strategy pattern. Those work pretty well, I take no offense
to their existence.
On the other hand, if we take a look at the OOP side, its not all so rosy suddenly.
There seems to be multiple reasons to apply the strategy pattern:
.=======================.
I Reasons to strategize I
`=======================`
â
â .------------------.
âââ| Trivially needed |
â | new class |
â `------------------`
â
â .------------------.
âââ| Cope for lack of |
| free functions |
`------------------`
So, as I was attempting to come up with a simpler example than HFDP's duck hierarchy,
I kept coming up with concepts that scream "I AM MY OWN CLASS". For example ÄMagicwandÄs
with engraved behaviour, but then there was no way to gaslight the reader that the
concept we are arriving to is not a ÄSpellÄ. Then as I applied complexity, I realized
the whole dilemma of this design arose from being unable to pinpoint the problem
and not it being inherently harder than say prototyping a function.
For the second part I wish you to refer to the previously mentioned duck example.
However, assuming you are unable to reference the original or dont care enough,
here is the quick rundown:
> Your current design contains the following hierarchy
âââââââââââââââââââ
â class Duck â
â£ââââââââââââââââââ«
â var duckyness; â
â void quack(); â
âââââââââââââââââââ
/ \
/ \
/ \
/ \
/ \
/ \
ââââââââââââââââââââââ ââââââââââââââââââââââ
â class MallardDuck â â class ReadHeadDuck â
â£âââââââââââââââââââââ« â£âââââââââââââââââââââ«
â var duckyness; â â var duckyness; â
â void quack(); â â void quack(); â
ââââââââââââââââââââââ ââââââââââââââââââââââ
> You are asked to add a RubberDuck
> Oh no! rubber ducks cannot quack! they squeak
> After juggling terrible ideas such as a quackable interface implemented by the children,
Strategies save the day
âââââââââââââââââââ âââââââââââââââââââ
â class Duck â â interface Quack â
â£ââââââââââââââââââ« â£ââââââââââââââââââ«
â var duckyness; â â void quack(); â
â var quack; â âââââââââââââââââââ
âââââââââââââââââââ | |
/ | \ | |
/ | \ | |
/ | \ | |
/ | \ | |
/ | \ | |
/ | \ | |
ââââââââââââââââââââââ ââââââââââââââââââââââ ââââââââââââââââââââââ | |
â class MallardDuck â â class ReadHeadDuck â â class RubberDuck â .-----------. .-------------.
â£âââââââââââââââââââââ« â£âââââââââââââââââââââ« â£âââââââââââââââââââââ« | class Quack | | class Squeak |
â var duckyness; â â var duckyness; â â var duckyness; â `---,-------` `-------------`
â var quack; â â var quack; â â var quack; â- - - - - - - - - - - -'
ââââââââââââââââââââââ ââââââââââââââââââââââ ââââââââââââââââââââââ :
: :
'- - - - - - - - -'- - - - - - - - - - - - - - - - - '
Ok, now lets think about this critically. The quack interface describes a single behaviour
that does not require internal state.
We used to have those things actually, they were called functions.
Seriously, 2 new classes and 1 additional interface is introduced to describe 2 behaviours.
Our source got more complex, bloated, dependant -as there are new couplings, never mind how
close they are-, and more verbose to extend. If thats not a work around I dont know what is.
Digging a little further, does Quack look encapsulated to you? Because to me she seems like a
free use whore pretending to be better than her ancestors under the banner of self-expression,
but I digress.
As a minor note, I would like to poke fun, how without optimizations the ABOVE will be
oh-so-slightly slower than the procedural equivalent because now we have to instantiate
quacks amongst other things.
"But Anon, you ignored rockets being strapped to ducks during the simulation,\
which modifies their fly behaviour" - I hear you say. You are correct.
This does mean that we will have to change behaviour at runtime.
Which, again, leaves us with scenario 1. Procedurally speaking, having a strategy
would be a pattern avoiding strangely placed and convoluted logical blocks, but
to replicate the problem in OOP, you would need a hierarchy of strangely placed
and convoluted logical blocks, at which point it should be obvious to anyone
something ÄÄveryÄÄ wrong is going on.