Design Patterns and Graphical User Interfaces Horstmann 5-5.4.1, 5.4.3-5.7 Design patterns • Design Patterns • • • • • Iterator Model-View-Controller and Observer Strategy Composite Decorator Design patterns • For each design pattern – Prototypical example – Context, problem – Solution, decoupling/interface – UML diagram • Patterns – Iterator, observer, strategy, composite, decorator Design patterns • Design Patterns • Iterator • • • • Model-View-Controller and Observer Strategy Composite Decorator Example: accessing elements in an ArrayList ArrayList<String> filmList = new ArrayList<String>(); filmList.add(”E.T.”); filmList.add(”Gran Torino”); • Printing all elements for (String film : filmList) System.out.println(film); • Printing all elements using iterator Iterator<String> iter = filmList.iterator(); while (iter.hasNext()) System.out.println(iter.next()); • Printing all elements ”manually” for (int i=0; i< filmList.size(); i++) System.out.println(filmList.get(i)); Example: Accessing elements in arbitrary container public Class FilmCatalogue { private String[] films = {”Dogville”,”Chinatown”}; public String get(int i) {return films[i];} public int size() {return films.length;} } • Uses encapsulation: YES • Fully decoupled: NO – Only ”manual” printing of elements in a FilmCatalogue object possible – very inefficient if array representation changed to linked lists Better: decoupling with iterator: public class FilmCatalogue implements Iterable<String> { public Iterator<String> iterator() { return new Iterator<String>() { private int position = 0; public boolean hasNext() {return position<films.length;} public String next() { if (hasNext()) return films[position++]; else return null; } ... }; } ... } Example: accessing elements in iterable FilmCatalogue FilmCatalogue filmList = new ArrayList<String>(); filmList.add(”E.T.”); filmList.add(”Gran Torino”); FilmCatalogue filmList = new FilmCatalogue(); • Printing all elements for (String film : filmList) System.out.println(film); • Printing all elements using iterator Iterator<String> iter = filmList.iterator(); while (iter.hasNext()) System.out.println(iter.next()); • Printing all elements ”manually” for (int i=0; i< filmList.size(); i++) System.out.println(filmList.get(i)); Iterator Pattern Context • An aggregate object contains element objects • Clients need access to the element objects • The aggregate object should not expose its internal structure • Multiple clients may want independent access Solution • Define an iterator that fetches one element at a time • Each iterator object keeps track of the position of the next element • If there are several aggregate/iterator variations, it is best if the aggregate and iterator classes realize common interface types. Iterator Pattern Iterator Pattern EXAMPLE Iterable <String> Iterator <String> iterator() next() ! hasNext() next() FilmCatalogue anonymous Library myLib = new Library(...); QUIZ Which of the code pieces obey the iterator pattern in the UML diagram ? 1.None 2.A only 3.B only 4.C only 5.D only 6.Two of A,B,C,D 7.Three of A,B,C,D 8.All of A,B,C,D 9.I don’t know A for (Book text : myLib) System.out.println(text); B Iterator<Book> iter = myLib.iterator(); while (iter.hasNext()) System.out.println(iter.next()); C Book[] list = myLib.getBooks(); for (int i=0; i< list.length; i++) System.out.println(list[i]); D for (Book text : myLib.getBooks()) System.out.println(text); Design patterns • Design Patterns • Iterator • Model-View-Controller and Observer • Strategy • Composite • Decorator Model/View/Controller Extra/changed view transparent to content Model/View/Controller • Model: data structure, no visual representation • Views: visual representations • Controllers: user interaction • Views/controllers update model • Model tells views that data has changed • Views redraw themselves Model/View/Controller Button / Listener • recall old example helloButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { textField.setText("Hello, World"); } } ); Observer Pattern • Model notifies views when something interesting happens • Button notifies action listeners when something interesting happens • Views attach themselves to model in order to be notified • Action listeners attach themselves to button in order to be notified • Generalize: Observers attach themselves to subject Observer Pattern Observer Pattern JButton ActionListener addActionListener() actionPerformed() anonymous Display Components Button Components QUIZ Which interpretations are reasonable? 1.None 2.a 3.b 4.c 5.a+b 6.a+c 7.b+c 8.a+b+c 9.I dont’t know a) MVC: Frame is Model Display Components are Views Buttons are Controllers b) MVC: Model is not visible, but contains a number Display Components are Views Listeners attached to Buttons are Controllers c) Observer: A Button is a Subject A Listener attached to a button is an Observer Design patterns • Design Patterns • Iterator • Model-View-Controller and Observer • Strategy • Composite • Decorator GUI: components and containers textfield component 3 button components label component frame container with 5 components (textfield, 3 buttons, label) Layout Managers • • • • • User interfaces made up of components Components placed in containers Container needs to arrange components Swing doesn't use hard-coded pixel coordinates Advantages: – Can switch "look and feel" – Can internationalize strings • Layout manager controls arrangement Layout Managers Layout Managers Example JPanel decDisplay = new JPanel(); final JTextField digits = new JTextField(“98",15); decDisplay.add(new JLabel("Decimal:")); decDisplay.add(digits); JPanel Default : FlowLayout JPanel display = new JPanel(); display.setLayout(new BorderLayout()); display.add(decDisplay, BorderLayout.NORTH); display.add(binDisplay, BorderLayout.SOUTH); BorderLayout Example JPanel keyboard = new JPanel(); keyboard.setLayout(new GridLayout(2,2)); keyboard.add(new JButton("0")); keyboard.add(new JButton("inc")); keyboard.add(new JButton("1")); keyboard.add(new JButton("dec")); JFrame f = new JFrame(); f.add(display,BorderLayout.NORTH); f.add(keyboard,BorderLayout.CENTER); GridLayout JFrame Default : BorderLayout Strategy Pattern • Pluggable strategy for layout management • Layout manager object responsible for executing concrete strategy • Generalizes to Strategy Design Pattern • Other manifestation: Comparators Comparator comp = new CountryComparatorByName(); Collections.sort(countries, comp); Strategy Pattern Context • A class can benefit from different variants for an algorithm • Clients sometimes want to replace standard algorithms with custom versions Solution • Define an interface type that is an abstraction for the algorithm • Actual strategy classes realize this interface type. • Clients can supply strategy objects • Whenever the algorithm needs to be executed, the context class calls the appropriate methods of the strategy object Strategy Pattern Strategy Pattern Comparator Collections Compare() anonymous Strategy Pattern Container LayoutManager layoutContainer() BorderLayout QUIZ Which versions of Graph class use strategy pattern? 1. None 2. A 3. B 4. A,B 5.I don’t know public class Graph { private Function f = new Logarithm(); A public draw() { plot(1,f.evaluate(1)); … } } public class Graph { private Function f; public Graph(Function fun) { f=fun; } B public draw() { plot(1,f.evaluate(1)); … } } Design patterns • • • • Design Patterns Iterator Model-View-Controller and Observer Strategy • Composite • Decorator Containers and Components • Containers collect GUI components • Sometimes, want to add a container to another container • Container should be a Component • Composite design pattern • Composite method typically invoke component methods • E.g. Container.getPreferredSize invokes getPreferredSize of components Composite Pattern Context • Primitive objects can be combined to composite objects • Clients treat a composite object as a primitive object Solution • Define an interface type that is an abstraction for the primitive objects • Composite object collects primitive objects • Composite and primitive classes implement same interface type. • When implementing a method from the interface type, the composite class applies the method to its primitive objects and combines the results Composite Pattern Composite Pattern Component JButton getPreferredSize() JPanel QUIZ Does UML and code for paint methods realize composite design pattern? 1.Yes, both UML and code 2.Only UML 3.Only code 4.Neither UML nor code 5.I don’t know class Rectangle: public void paint(Graphics2D g) { g.draw(. . .); } class Composite: private ArrayList<Rectangle> cubes; public void paint(Graphics2D g) { for (Rectangle r: cubes) r.paint(g); } Design patterns • • • • • Design Patterns Iterator Model-View-Controller and Observer Strategy Composite • Decorator Scroll Bars • Scroll bars can be attached to components • Approach #1: Component class can turn on scroll bars • Approach #2: Scroll bars can surround component JScrollPane pane = new JScrollPane(component); • Swing uses approach #2 • JScrollPane is again a component Decorator Pattern Context • Component objects can be decorated (visually or behaviorally enhanced) • The decorated object can be used in the same way as the undecorated object • The component class does not want to take on the responsibility of the decoration • There may be an open-ended set of possible decorations Solution • Define an interface type that is an abstraction for the component • Concrete component classes realize this interface type. • Decorator classes also realize this interface type. • A decorator object manages the component object that it decorates • When implementing a method from the component interface type, the decorator class applies the method to the decorated component and combines the result with the effect of the decoration. Decorator Pattern Decorator Pattern JComponent JTextArea paintComponent() JScrollPane QUIZ Does UML and code for paint methods realize decorator design pattern? 1.Yes, both UML and code 2.Only UML 3.Only code 4.Neither UML nor code 5.I don’t know class Rectangle: public void paint(Graphics2D g) { g.draw(. . .); } class Decor: private Cubism cube; public void paint(Graphics2D g) { g.draw(new Rectangle2D(. . .)); g.draw(... cube ...); }