I'm still trying to work out which programming patterns are the right ones to follow. Sometimes abstraction is good (make code work anywhere!), sometimes it's bad (unnecessary complexity!). Sometimes code reuse is good (proven edge cases!), sometimes it's bad (dependencies!). It seems to largely be a game of choosing between pros/cons as you go. Strict adherence to any pattern seems just as dangerous as following none.
This seems especially true in Java/OOP land, for whatever reason.