1 More Design Patterns CS 3331 Fall 2009
2 GoF Patterns Creational StructuralBehavioral Abstract FactoryAdapter Chain of Responsibility Builder BridgeCommand Factory MethodCompositeInterpreter Prototype DecoratorIterator Singleton FaçadeMediator FlyweightMemento ProxyObserver State Strategy Template Method Visitor E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995.
3 Outline Factory method Adapter Observer Composite
4 Bouncing Ball Revisited To bounce different types of balls BouncingBall Circle draw() Ball draw() Rectangle draw() 1 Q: What design pattern is used?
5 Creating Different Balls Q: What’s the problem with this kind of code? public class BouncingBall extends java.applet.Applet { private Ball ball; private static final String BALL_TYPE = “circle”; public BouncingBall() { if (“circle”.equals(BALL_TYPE)) { ball = new Circle(); } else if (“rectangle”.equals(BALL_TYPE)) { ball = new Rectangle(); } else { ball = new Circle(); } // the rest of code … }
6 A Better Way of Creating Balls Q: Why is this code better? public class BouncingBall extends java.applet.Applet { private Ball ball; public BouncingBall() { ball = createBall(); } protected Ball createBall() { return new Circle(); } // the rest of code … }
7 Example (Cont.) How to bounce a triangle ball? public class TriangleBouncingBall extends BouncingBall { protected Ball createBall() { return new Triangle(); } private static class Triangle implements Ball { public void draw() { /* … */ } // the rest of code here … }
8 Factory Method To define an interface for creating an object, but let subclasses to decide which class to instantiate. ProductConcreteProduct AbstractClass factoryMethod() operation() ConcreteClass factoryMethod() return new ConcreteProduct(); p = factoryMethod(); Q: Have we seen a similar design pattern before?
9 Exercise Refactor the following applet to apply Factory Method. public class ConfigurableClock extends java.applet.Applet { private ClockDisplay display; public ConfigurableClock() { display = new DigitalDisplay(); } // the rest of code here … } Also, define a subclass that uses an AnalogDisplay.
10 Outline Factory method Adapter Observer Composite
11 Bouncing Cars How to bounce instances of the class Car? public class BouncingCar extends BouncingBall { protected Ball createBall() { return new Car(); } public class BounceableCar extends Car implements Ball { public void draw() { /* … */ } // the rest of code here … } BounceableCar();
12 Adapter To convert the interface of a class into another interface that clients expect. Client Target operation() Adaptee operation() adaptee.operation(); Adapter operation()
13 Adapter (Cont.) Client Target operation() Adaptee operation() Adapter
14 Exercise Define an adapter class so that the class Teacher can also work with the client. Staff Teacher +Teacher(n: String) +getName(): String Student +Student(n: String) +getName(): String Client +doIt(s: Student)
15 Outline Factory method Adapter Observer Composite
16 A Closer Look at JButton How the button events (e.g., clicking) are handled? JButton button = new JButton(“Ok”); button.addActionListener(new OkButtonListener()); … private class OkButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println(“Ok button pressed!”); }
17 Static Structure JButton addActionListener() removeActionListener() fireActionPerformed() listeners 0..* for each l in listeners l.actionPerformed(e); ActionListener actionPerformed () OkButtonListener actionPerformed()
18 Dynamic Behavior l : OkButtonListener addActionListener(l) fireActionPerformed(e) actionPerformed(e) > getSource() e : ActionEventbutton : JButton
19 Observer Pattern Intent To define relationship between a group of objects such that whenever one object is updated all others are notified automatically. Context Multiple objects depend on the state of one object. Set of dependent objects may change at runtime. Solution Allow dependent objects to register with object of interest, and notify them of updates when state changes.
20 Structure attach(Observer) detach(Observer) notifyChange() Subject update() Observer getState() setState() ConcreteSubject update() ConcreteObserver public void update() {... subject.getState()... } public void notifyChange() { for each o in observers o.update(); } observers 0..* subject ConcreteObserver may depend on ConcreteSubject, but not the other way around!
21 Participants Subject Knows its observers Provides interface for attaching and detaching observers Observer Defines an updating interface ConcreteSubject Stores state of interest Sends notification to observers on state change ConcreteObserver Maintains a reference to a concrete subject. Stores state that should stay consistent with the subject’s. Implements the updating interface to keep its state consitent with the subject’s.
22 Collaborations
23 Example – Observable Counters public class Counter { private int cnt; private List observers = new ArrayList(); public int val() { return cnt; } public void incr() { cnt++; for (Iterator i = observers.iterator(); i.hasNext(); ) { ((CounterObserver) i.next()).valueChanged(); } } public void addObserver(CounterObserver o) { observers.add(o); } } public interface CounterObserver { void valueChanged(); }
24 Example (Cont.) public class CounterApplet extends java.applet.Applet implements CounterObserver { private Counter counter = new Counter(); private JTextField display = new JTextField(4); public CounterApplet() { add(display); JButton incr = new JButton(“incr”); incr.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { counter.incr(); } }); add(incr); counter.addObserver(this); } public void valueChanged() { display.setText(Integer.toString(counter.val())); } incr 12
25 Exercise Make the following class observable. public class Suspect { public void meetWith(Person p) { /* … */ } }
26 Outline Factory method Adapter Observer Composite
27 Composite Design Pattern To allow clients to treat both single components and collections of components identically To define recursive data structures such as trees Client uses Leaf operation() Component operation() Composite operation() add(Component) remove(Component) *
28 Example Composing GUI public class MyApplet extends java.applet.Applet { public MyApplet() { add(new Label(“My label”)); add(new Button(“My button”)); Panel myPanel = new Panel(); myPanel.add(new Label(“Sublabel”)); myPanel.add(new Button(“Subbutton”)); add(myPanel); } } Q: How can we add any widgets including panels to applets (i.e., panels)?
29 AWT Components
30 Bouncing Multiple Balls BouncingBall Circle draw() Ball draw() Rectangle draw() 1 private Ball ball; public void paint(Graphics g) { // … ball.draw(g); // … }
31 Bouncing Multiple Balls (Cont.) BouncingBall Circle draw() Ball draw() Rectangle draw() 1..* private Set balls; public void paint(Graphics g) { // … for (Iterator i = balls.iterator(); i.hasNext(); ) { ((Ball) i.next()).draw(g); } // … }
32 Using Composite Pattern BouncingBall Ball draw(Graphics) 1 Circle draw(Graphics) Rectangle draw(Graphics) BallGroup add(Ball) remove(Ball) draw(Graphics) 1..*
33 Using Composite Pattern (Cont.) public class BallGroup extends Ball { private Set balls = new HashSet(); // each b in balls is instanceof Ball public void add(Ball b) { balls.add(b); } public void remove(Ball b) { balls.remove(b); } public void paint(Graphics g) { for (Iterator i = balls.iterator(); i.hasNext(); ) { ((Ball) i.next()).draw(g); }
34 Exercise How to represent an expression, E, where E is a number or E + E, e.g., 1, 1 + 2, , etc? Number value() evaluate() Expression evaluate() BinaryExpression left() right() evaluate() 2
35 Exercise (Cont.) Write the classes Expression, Number, and BinaryExpression of the previous example.