47
Slide 1 Object-Oriented Design Patterns part II and a short introduction to GUI

Object-Oriented Design Patterns part II and a short

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Object-Oriented Design Patterns part II and a short

Slide 1

Object-Oriented Design Patterns part II and a short introduction to GUI

Page 2: Object-Oriented Design Patterns part II and a short

Slide 2

Lesson OverviewTopics covered

(1) The Composite Design Pattern

(2) The Adapter Design Pattern

(3) A short introduction to GUI components

(4) Event Handling Mecahnisms

Page 3: Object-Oriented Design Patterns part II and a short

Slide 3

The Composites Design PatternIntent

Compose objects into tree structures to represent part-whole hierarchies.

Composite lets clients treat individual objects and compositions of objects uniformly.

This is called recursive composition.

Page 4: Object-Oriented Design Patterns part II and a short

Slide 4

Composite Design Pattern (cont.)Motivation

Graphics application like drawing editors let the user build complex diagrams out of simple components.

The user can group components to form larger components, which in turn can be grouped to form still larger components.

A simple solution is to define classes for graphical primitives such as Text and Lines plus other classes that act as containers for these primitives. (bad idea, why?)

Page 5: Object-Oriented Design Patterns part II and a short

Slide 5

Composite Design Pattern (cont.)Motivation

Code that uses these classes must treat primitives and container objects differentlyl, even if most of the time the user treats them identically.

Having to distinguish these objects makes the application more complex.

The Composite design pattern describes how to use recursive composition so clients don't have to make this distinction.

Page 6: Object-Oriented Design Patterns part II and a short

Slide 6

Composite Design Pattern – Motiviation (cont.)The key is an abstract class that represents both primitives and containers.

For the graphic system, this class is Graphic: which declares operations like Draw that are specific for graphical objects, and also operations that all composite objects share, like operations for accessing and manging its children.

Page 7: Object-Oriented Design Patterns part II and a short

Slide 7

Composite Design Pattern – Motiviation (cont.)The Picture class allows to define aggregate Graphic objects.

Picture implements Draw to call the Draw method on its children, and it implements child-related operations accordingly.

Since Picture conforms to the Graphic interface, we can compose Picture objects recursively:

Page 8: Object-Oriented Design Patterns part II and a short

Slide 8

Composite Design Pattern Applicability

Use the Composite Pattern when

You want to represent part-whole hierarchies of objects. You want clients to be able to ignore the difference between

compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.

Page 9: Object-Oriented Design Patterns part II and a short

Slide 9

Composite Design Pattern Structure

Page 10: Object-Oriented Design Patterns part II and a short

Slide 10

Composite Design Pattern Collaborations

Clients use the Component class interface to interact with objects in the composite structure.

If the recipient is a Leaf, then the request is handled directly.

If it is a Composite, then it usually forwards requests to its child components, possibly performing additional operations before and/or after forwarding

Page 11: Object-Oriented Design Patterns part II and a short

Slide 11

Composite Design Pattern Consequences

Benefits:

Makes it easier to add new kinds of components – does not require change in the client code, and will also easily fit into existing structures.

Makes the clients simpler since they do not have to know if they are dealing with a leaf or a composite component – simplifies client code.

Liabilities:

Can make the design overtly general – harder to restrict the type of components of a composite.

Page 12: Object-Oriented Design Patterns part II and a short

Slide 12

Composite Design Pattern Implementation Issues

Explicit Parent References: A composite object knows its contained components, that is, its children. Should components maintain a reference to their parent component?

➔ Answer: Depends on application, but having these references supports the Chain of Responsibility pattern.

Page 13: Object-Oriented Design Patterns part II and a short

Slide 13

Composite Design Pattern Implementation Issues (cont.)

Child Management: Where should the child management methods (add(), remove(), getChild()) be declared?

➔ Option 1: In the Component class: Gives transparency, since all components can be treated the same. But it's not safe, since clients can try to do meaningless things to leaf components at run-time.

➔ Option 2: In the Composite class: Gives safety, since any attempt to perform a child operation on a leaf component will be caught at compile-time. But we lose transparency, since now leaf and composite components have different interfaces.

Page 14: Object-Oriented Design Patterns part II and a short

Slide 14

Composite Design Pattern Implementation Issues (cont.)

Child Management: Transparent Vs. Safe:

Page 15: Object-Oriented Design Patterns part II and a short

Slide 15

Composite Design Pattern Implementation Issues (cont.)

Component Management: Should Component maintain the list of components that will be used by a composite object? That is, should this list be an instance variable of Component rather than Composite?

➔ Better to keep this part of Composite and avoid wasting the space in every leaf object.

Child Ordering: Is child ordering important?

➔ Depends on application

Page 16: Object-Oriented Design Patterns part II and a short

Slide 16

Composite Design Pattern Implementation Issues (cont.)

Who should delete components?

➔ Not a problem in Java! The garbage collector will come to the rescue! In languages without garbage collection, its usually best to make a Composite responsible for deleting its children.

What's the best data structure to store components?

➔ Depends on application: a variety of data structures can be used to store children including: linked-lists, trees, arrays and hash-tables. Many times it isn't even necessary to use general-purpose data structures at all.

Page 17: Object-Oriented Design Patterns part II and a short

Slide 17

Composite Example no. 1Scenario:

A GUI system has window objects which can contain various GUI components (widgets) such as, buttons and text areas.

A window can also contain widget container objects which can hold other widgets.

Solution 1:

Design all the widgets with different interfaces for "updating" the screen?

Page 18: Object-Oriented Design Patterns part II and a short

Slide 18

Composite Example no. 1 We would then have to write a Window update() method as

follows: public class Window {

Button[] buttons;

Menu[] menus;

TextArea[] textAreas;

WidgetContainer[] containers;

Page 19: Object-Oriented Design Patterns part II and a short

Slide 19

Composite Example no. 1public void update() { //Class Window continued:

if (buttons != null)

for (int k = 0; k < buttons.length; k++)

buttons[k].draw();

if (menus != null)

for (int k = 0; k < menus.length; k++)

menus[k].refresh();

// Other widgets handled similarly.

if (containers != null)

for (int k = 0; k < containers.length; k++ )

containers[k].updateWidgets();

} ... } //end of class

Page 20: Object-Oriented Design Patterns part II and a short

Slide 20

Composite Example no. 1Solution 1:

Looks particularly bad! - It violates the Open-Closed Principle: If we want to add a new kind of widget, we have to modify the update() method of Window to handle it.

Solution 2:

We should always try to program to an interface, So, let's make all widgets support the Widget interface, either by being subclasses of a Widget class or implementing a Java Widget interface.

Page 21: Object-Oriented Design Patterns part II and a short

Slide 21

Composite Example no. 1 Now our update() method becomes: public class Window {

Widget[] widgets;

WidgetContainer[] containers;

public void update() {

if (widgets != null)

for (int k = 0; k < widgets.length; k++)

widgets[k].update();

if (containers != null)

for (int k = 0; k < containers.length; k++ )

containers[k].updateWidgets();

} ... }// of class

Page 22: Object-Oriented Design Patterns part II and a short

Slide 22

Composite Example no. 1Solution 2:

That looks better, but we are still distinguishing between widgets and widget containers

Solution 3: The Composite Pattern!

Page 23: Object-Oriented Design Patterns part II and a short

Slide 23

Composite Example no. 1 Now our update() method becomes: public class Window {

Component[] components;

public void update() {

if (components != null)

for (int k = 0; k < components.length; k++)

components[k].update();

}

}

Page 24: Object-Oriented Design Patterns part II and a short

Slide 24

The Java AWT Hierarchy (old version)

Page 25: Object-Oriented Design Patterns part II and a short

Slide 25

Java JFC and SwingJFC - Java Foundation Classes: encompass a group of features for building graphical user interfaces (GUIs) and adding rich graphics functionality and interactivity to Java applications.

JFC contains the following (incomplete list):

(1) Swing GUI Components – Windows, Buttons, Checkboxes...

(2) Pluggable Look-and-Feel Support - Gives any program that uses Swing components a choice of look and feel. For example, the same program can use either the Java or the Windows look and feel.

(3)Java 2D API - Enables developers to easily incorporate high-quality 2D graphics, text, and images in applications and applets.

Page 26: Object-Oriented Design Patterns part II and a short

Slide 26

Graphical HelloWorld Applicationimport javax.swing.*;

public class HelloWorldSwing {

public static void main(String[] args) {

//Schedule a job for the event-dispatching thread:

//creating and showing this application's GUI.

javax.swing.SwingUtilities.invokeLater(

new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

Page 27: Object-Oriented Design Patterns part II and a short

Slide 27

Graphical HelloWorld Applicationprivate static void createAndShowGUI() {

//Make sure we have nice window decorations.

JFrame.setDefaultLookAndFeelDecorated(true);

//Create and set up the window.

JFrame frame = new JFrame("HelloWorldSwing");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Add the ubiquitous "Hello World" label.

JLabel label = new JLabel("Hello World");

frame.getContentPane().add(label);

//Display the window.

frame.pack();

frame.setVisible(true); }

Page 28: Object-Oriented Design Patterns part II and a short

Slide 28

Result?

The HelloWorldSwing example has only one top-level container, a JFrame - Implemented as an instance of the JFrame class.

The Jframe class is a window that, by default, has decorations such as a border, a title, and buttons for iconifying and closing the window.

Applications with a GUI typically use at least one frame.

All Swing components descend from the JComponent class, except top level containers like JFrame.

Page 29: Object-Oriented Design Patterns part II and a short

Slide 29

Example 2import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

public class SwingApplication implements ActionListener {

private static String labelPrefix = "Number of button clicks: ";

private int numClicks = 0;

final JLabel label = new Jlabel( labelPrefix + "0 ");

//Specify the look and feel to use.

final static String LOOKANDFEEL = UIManager.getSystemLookAndFeelClassName();

Page 30: Object-Oriented Design Patterns part II and a short

Slide 30

Example 2 cont.public Component createComponents() {

JButton button = new JButton("I'm a Swing button!");

button.setMnemonic(KeyEvent.VK_I);

button.addActionListener(this);

label.setLabelFor(button);

/* An easy way to put space between a top-level container and its contents is to put the contents in a Jpanel that has an "empty" border.*/

JPanel pane = new JPanel(new GridLayout(0, 1));

pane.add(button);

pane.add(label);

pane.setBorder(BorderFactory.createEmptyBorder(

30,30,10,30));

return pane;

}

Page 31: Object-Oriented Design Patterns part II and a short

Slide 31

Example 2 cont.//The Event handling mechanism in Java (more details

in our next lesson)

public void actionPerformed(ActionEvent e) {

numClicks++;

label.setText(labelPrefix + numClicks);

}

Page 32: Object-Oriented Design Patterns part II and a short

Slide 32

Example 2 cont.private static void createAndShowGUI() {

//Make sure we have nice window decorations.

JFrame.setDefaultLookAndFeelDecorated(true);

//Create and set up the window.

JFrame frame = new JFrame("SwingApplication"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

SwingApplication app = new SwingApplication();

Component contents = app.createComponents();

frame.getContentPane().add(contents, BorderLayout.CENTER);

//Display the window.

frame.pack();

frame.setVisible(true);

}

Page 33: Object-Oriented Design Patterns part II and a short

Slide 33

Adding Swing Components into a GUI applicationLike most GUIs, the SwingApplication GUI contains a button and a label. Here's the code that initializes the button:

...// where instance variables are declared:

private static String labelPrefix = "Number of button clicks: ";

private int numClicks = 0;

...// in GUI initialization code:

final JLabel label = new JLabel(labelPrefix + "0 ");

...

label.setLabelFor(button);

...// in the event handler for button clicks:

label.setText(labelPrefix + numClicks);

Page 34: Object-Oriented Design Patterns part II and a short

Slide 34

Adding Swing Components into a GUI applicationNow that you know how to set up buttons, you also know much of what's needed to set up check boxes and radio buttons, as they all inherit from the AbstractButton class.

Check boxes are similar to radio buttons, but by convention their selection models are different. Any number of check boxes in a group--none, some, or all--can be selected.

On the other hand, by convention only one button can be selected from a group of radio buttons.

Page 35: Object-Oriented Design Patterns part II and a short

Slide 35

Button Examples

Page 36: Object-Oriented Design Patterns part II and a short

Slide 36

Adding Swing Components into a GUI applicationSwingApplication groups its label and button in a container (a JPanel) before adding the components to the frame. Here's the code that initializes the container:

JPanel panel = new JPanel(new GridLayout(0,1));

panel.add(button);

panel.add(label);

panel.setBorder(BorderFactory.createEmptyBorder(...));

Page 37: Object-Oriented Design Patterns part II and a short

Slide 37

Handling EventsEvery time the user types a character or pushes a mouse button, an event occurs.

Any object can be notified of the event.

All the object has to do is implement the appropriate interface and be registered as an event listener on the appropriate event source.

SwingApplication class implements an event handler for button clicks (action events).

Page 38: Object-Oriented Design Patterns part II and a short

Slide 38

Handling EventsThe event handling code:

public class SwingApplication implements ActionListener {

...

JButton button = new JButton("I'm a Swing button!");

button.addActionListener(this);

....

public void actionPerformed(ActionEvent e) {

numClicks++;

label.setText(labelPrefix + numClicks);

}

}

Page 39: Object-Oriented Design Patterns part II and a short

Slide 39

Handling EventsEvery event handler requires three pieces of code:

(1) In the declaration for the event handler class, one line of code specifies that the class either implements a listener interface or extends a class that implements a listener interface. For example:

public class MyClass implements ActionListener {

(2) Another line of code registers an instance of the event handler class as a listener on one or more components. For example:

someComponent.addActionListener(instanceOfMyClass);

Page 40: Object-Oriented Design Patterns part II and a short

Slide 40

Handling EventsEvery event handler requires three pieces of code: (cont.)

(3) The event handler class has code that implements the methods in the listener interface. For example:

public void actionPerformed(ActionEvent e) {

...//code that reacts to the action...

}

Page 41: Object-Oriented Design Patterns part II and a short

Slide 41

Handling EventsIn general, to detect when the user clicks an onscreen button (or does the keyboard equivalent), a program must have an object that implements the ActionListener interface.

The program must register this object as an action listener on the button (the event source), using the addActionListener method.

When the user clicks the onscreen button, the button fires an action event.

This results in the invocation of the action listener's actionPerformed method (the only method in the ActionListener interface).

Page 42: Object-Oriented Design Patterns part II and a short

Slide 42

Handling EventsThe single argument to the method is an ActionEvent object that gives information about the event and its source.

Page 43: Object-Oriented Design Patterns part II and a short

Slide 43

Event TypesSwing components can generate many kinds of events. Here are some examples:

Page 44: Object-Oriented Design Patterns part II and a short

Slide 44

Swing Visual Components

Page 45: Object-Oriented Design Patterns part II and a short

Slide 45

Swing Visual Components

Page 46: Object-Oriented Design Patterns part II and a short

Slide 46

Swing Visual Components

Page 47: Object-Oriented Design Patterns part II and a short

Slide 47

Swing Visual Components