Design Patterns: CSCI 4448/5448: Object-Oriented Analysis & Design Lecture 7 - 09/18/2012
Design Patterns: CSCI 4448/5448: Object-Oriented Analysis & Design Lecture 7 - 09/18/2012
• Discuss why design patterns are important and what advantages they provide
• In 1995, a book was published by the “Gang of Four” called Design Patterns
• although many pattern authors abandoned the criteria of having to find the
pattern in 3 shipping systems
• Unfortunately, many people feel like they should become experts in OO A&D
before they learn about patterns
• our book takes a different stance: learning about design patterns will help
you become an expert in OO A&D
• Patterns (structures and relationships that appear over and over again in
many different well designed objects) provide an objective basis for
judging design
• His 1979 book called “The Timeless Way of Building” that asks the
question “Is quality objective?”
• His answer was “yes” that it was possible to objectively define “high
quality” or “beautiful” buildings
• especially if both objects were used to solve the same type of problem
• “Each pattern describes a problem which occurs over and over again in
our environment and then describes the core of the solution to that
problem, in such a way that you can use this solution a million times over,
without ever doing it the same way twice.”
• He also felt that multiple patterns applied together can help to solve complex
architectural problems
• Are there problems in software that occur all the time that can be solved in
somewhat the same manner?
• Many people felt the answer to these questions was “yes” and this initial work
influenced the creation of the Design Patterns book by the Gang of Four
• Design patterns, then, assert that the quality of software systems can be
measured objectively
• What is present in a good quality design (X’s) that is not present in a poor
quality design?
• What is present in a poor quality design (Y’s) that is not present in a good
quality design?
• We would then want to maximize the X’s while minimizing the Y’s in our own
designs
• Patterns let us
• reuse solutions that have worked in the past; why waste time reinventing
the wheel?
• You don’t have to waste time explaining what you mean since you
both know the Strategy pattern
• Design patterns provide you not with code reuse but with experience reuse
• Design patterns can show you how to apply those concepts to achieve those
goals
• You’ll be able to think more abstractly and not get bogged down in
implementation details too early in the process
• or
• Should I make the joint by cutting down into the wood and then going
back up 45 degrees and…
• The latter gets bogged down in the details of cutting the wood such that
you don’t know what problem is being solved
• They know that dovetail joints are higher quality than miter joints but with
higher costs
• Knowing that, they can debate whether the higher quality is needed in the
situation they are in
• “I have this one object with some important information and these other
objects over here need to know when its information changes. These other
objects come and go. I’m thinking I should separate out the notification and
client registration functionality from the functionality of the object and just let
it focus on storing and manipulating its information. Do you agree?”
• vs.
• Junior developers see that the design patterns discussed by more senior
developers are valuable and are motivated to learn them
• Improved maintainability
• code to an interface
• Since they favor delegation, they help you avoid the creation of large
inheritance hierarchies, reducing complexity
• SimUDuck: a “duck pond simulator” that can show a wide variety of duck
species swimming and quacking
MallardDuck RedheadDuck
display() display()
• But a request has arrived to allow ducks to also fly. (We need to stay
ahead of the competition!)
MallardDuck RedheadDuck
display() display()
Duck
quack()
swim()
display()
fly()
MallardDuck RedheadDuck
display() display()
• code reuse, only one fly() and quack() method vs. multiple (pro)
• specificity: only those subclasses that need a fly() method get it (pro)
• Use of abstract base class over an interface? Could do it, but only in
languages that support multiple inheritance
• For this particular problem, the “what varies” is the behaviors between
Duck subclasses
• We need to pull out behaviors that vary across subclasses and put
them in their own classes (i.e. encapsulate them)
• Take any behavior that varies across Duck subclasses and pull them out of Duck
• Create two sets of classes, one that implements fly behaviors and one that
implements quack behaviors
• Code to an Interface
• We’ll make use of the “code to an interface” principle and make sure that each
member of the two sets implements a particular interface
• Additional benefits
• Other classes can gain access to these behaviors (if that makes sense) and we can
add additional behaviors without impacting other classes
• Or, we can “code to a supertype” and instead define an abstract base class
which classes can access via inheritance.
• When we say “code to an interface” it implies that the object that is using the
interface will have a variable whose type is the supertype (whether its an
interface or abstract base class) and thus
• We’ll add two attributes that store the desired behavior and we’ll rename fly()
and quack() to performFly() and performQuack()
• this last step is meant to address the issue of it not making sense for a
DecoyDuck to have methods like fly() and quack() directly as part of its
interface
DuckSimulator.java (Part 1)
13 d.swim();
14 }
15 }
16
17 public static void main(String[] args) { Note: all variables
18
19 List<Duck> ducks = new LinkedList<Duck>();
are of type Duck,
20 not the specific
21 Duck model = new ModelDuck(); subtypes; “code to
22
23 ducks.add(new DecoyDuck()); interface” in action
24 ducks.add(new MallardDuck());
25 ducks.add(new RedHeadDuck());
26 ducks.add(new RubberDuck());
27 ducks.add(model);
28
29 processDucks(ducks);
30
31 // change the Model Duck's behavior dynamically Note: here we see
32 model.setFlyBehavior(new FlyRocketPowered()); the power of
33 model.setQuackBehavior(new Squeak());
34 delegation. We can
35 processDucks(ducks); change behaviors
36 }
37 } at run-time
38
© Kenneth M. Anderson, 2012 33
DuckSimulator.java (Part 2)
1 import java.util.LinkedList;
2 import java.util.List;
3
4 public class DuckSimulator {
5
6 public static void processDucks(List<Duck> ducks) {
7 for (Duck d : ducks) {
8 System.out.println("----------------------------------------");
9 System.out.println("Name: " + d.getClass().getName());
10 d.display();
11 d.performQuack();
12 d.performFly();
13 d.swim();
14 }
15 }
16
17 public static void main(String[] args) {
18 Because of abstraction and polymorphism, processDucks()
19 consists of nice,ducks
List<Duck> clean,=robust & extensible code!
new LinkedList<Duck>();
20
21 Duck model = new ModelDuck();
© Kenneth M. Anderson, 2012 34
22
Not Completely Decoupled
• No!
• The solution that we applied to this design problem is known as the Strategy
Design Pattern
• Code to an Interface
• Delegation
Algorithm is pulled out of Client. Client only makes use of the public
interface of Algorithm and is not tied to concrete subclasses.
Client can change its behavior by switching among the various concrete
algorithms
© Kenneth M. Anderson, 2012 37
Review of Delegate (I)
• We focused on the first one and saw how default behaviors of the Table
View could be influenced by the delegate
• In particular, we saw how the Table View would not show its “move
handles” during edit mode if the delegate did not implement a
method that handles moving rows
• Purpose of Delegate:
• Structure
Client
DelegateInterface
Host
delegate «Interface» «implements» Delegate
methodA()
customizeMethodA() customizeMethodA()
methodB()
customizeMethodB() ...
...
...
• Design Patterns