Design Patterns: not code reuse, EXPERIENCE reuse. - Think at the level of patterns, not objects, by using a shared vocabulary Go over the SimUDuck simulator: - Duck class - Change ducks to Fly by modifying superclass - What about exceptions to the rule? - Change duck subclasses to implement interfaces - Flyable - Quackable - What do we think about these designs? - Ease of change - Ease of understanding What's the one constant in software development? CHANGE! Principle: Identify the aspects of your application that vary and separate them from what stays the same. - In short, "encapsulate" what varies (in a separate class) - Create instance variables for it, and delegate to it. - Behavior can be customized in the constructor, and changed at run time. - Then you can reuse this stuff separately (e.g., Duck behaviors and Ducks can evolve separately, with the former used by other classes too). - Particularly handy of behaviors can vary in non-hierarchical ways across a group of subclasses. - But how do I know what's likely to vary in the future? - As you build your app you figure it out - You can see what varies in the design stage; even if it doesn't vary in the future it might make for a cleaner separation now. Principle: Program to an interface, not an implementation - Abstract idea: abstract class OR Java interface - Why? Then you don't depend on implementation details, just the types. - Declare variables as interfaces (supertypes), rather than implementations, so you don't rely on the particular object types; these can change later. - E.g., Animal x = new Dog() (but factory is better; covered later) - Probably you often are thinking this, but you don't bother to make the interface Animal. That is, the interface should represent the LEAST set of behaviors that the clients who use it need to know about. If you reveal more behaviors by passing object types, the clients could come to depend on them. Principle: Favor composition over inheritance - That's what all this delegation business with duck behaviors is about. It's more flexible, less painful, and can be more robust. But it might be more overhead. Relationships: - IS-A (a class via subclassing) - HAS-A (an instance variable) - IMPLEMENTS (an interface, similar to IS-A) Strategy pattern (p. 24)