Contents [0/55] |
Object-Oriented Design & Patterns [1/55] |
Chapter Topics [2/55] |
Adapters [3/55] |
file:horstmann/ch10_adapter/IconAdapter.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package horstmann.ch10_adapter; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.Icon; import javax.swing.JComponent; /** An adapter that turns an icon into a JComponent. */ @SuppressWarnings("serial") public class IconAdapter extends JComponent { /** Constructs a JComponent that displays a given icon. @param icon the icon to display */ public IconAdapter(Icon icon) { this.icon = icon; } public void paintComponent(Graphics g) { icon.paintIcon(this, g, 0, 0); } public Dimension getPreferredSize() { return new Dimension(icon.getIconWidth(), icon.getIconHeight()); } private Icon icon; }
file:horstmann/ch10_adapter/IconAdapterTester.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package horstmann.ch10_adapter; import java.awt.BorderLayout; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JFrame; /** This program demonstrates how an icon is adapted to a component. The component is added to a frame. */ public class IconAdapterTester { public static void main(String[] args) { Icon icon = new CarIcon(300); JComponent component = new IconAdapter(icon); JFrame frame = new JFrame(); frame.add(component, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } }
The ADAPTER Pattern [4/55] |
The ADAPTER Pattern [5/55] |
The ADAPTER Pattern [6/55] |
The ADAPTER Pattern [7/55] |
Name in
Design Pattern |
Actual Name
(Icon->Component) |
Adaptee |
Icon |
Target |
JComponent |
Adapter |
IconAdapter |
Client |
The class that wants to add
icons into a container |
targetMethod() |
paintComponent(), getPreferredSize() |
adapteeMethod() |
paintIcon(), getIconWidth(), getIconHeight() |
The ADAPTER Pattern [8/55] |
The ADAPTER Pattern [9/55] |
Name in
Design Pattern |
Actual Name
(Stream->Reader) |
Adaptee |
InputStream |
Target |
Reader |
Adapter |
InputStreamReader |
Client |
The class that wants to read
text from an input stream |
targetMethod() |
read
(reading a character) |
adapteeMethod() |
read (reading a byte) |
User Interface Actions [10/55] |
User Interface Actions [11/55] |
The Action Interface Type [12/55] |
The Action Interface Type [13/55] |
Action Example [14/55] |
file:horstmann/ch10_command/CommandTester.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package horstmann.ch10_command; import java.awt.BorderLayout; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JTextArea; import javax.swing.JToolBar; /** This program demonstrates action objects. Two actions insert greetings into a text area. Each action can be triggered by a menu item or toolbar button. When an action is carried out, the opposite action becomes enabled. */ public class CommandTester { public static void main(String[] args) { JFrame frame = new JFrame(); JMenuBar bar = new JMenuBar(); frame.setJMenuBar(bar); JMenu menu = new JMenu("Say"); bar.add(menu); JToolBar toolBar = new JToolBar(); frame.add(toolBar, BorderLayout.NORTH); JTextArea textArea = new JTextArea(10, 40); frame.add(textArea, BorderLayout.CENTER); GreetingAction helloAction = new GreetingAction( "Hello, World", textArea); helloAction.putValue(Action.NAME, "Hello"); helloAction.putValue(Action.SMALL_ICON, new ImageIcon("hello.png")); GreetingAction goodbyeAction = new GreetingAction( "Goodbye, World", textArea); goodbyeAction.putValue(Action.NAME, "Goodbye"); goodbyeAction.putValue(Action.SMALL_ICON, new ImageIcon("goodbye.png")); helloAction.setOpposite(goodbyeAction); goodbyeAction.setOpposite(helloAction); goodbyeAction.setEnabled(false); menu.add(helloAction); menu.add(goodbyeAction); toolBar.add(helloAction); toolBar.add(goodbyeAction); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } }
file:horstmann/ch10_command/GreetingAction.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package horstmann.ch10_command; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JTextArea; /** This action places a greeting into a text field and afterwards disables itself and enables its opposite action. */ @SuppressWarnings("serial") public class GreetingAction extends AbstractAction { /** Constructs a greeting action. @param greeting the string to add to the text area @param textArea the text area to which to add the greeting */ public GreetingAction(String greeting, JTextArea textArea) { this.greeting = greeting; this.textArea = textArea; } /** Sets the opposite action. @param action the action to be enabled after this action was carried out */ public void setOpposite(Action action) { oppositeAction = action; } public void actionPerformed(ActionEvent event) { textArea.append(greeting); textArea.append("\n"); if (oppositeAction != null) { setEnabled(false); oppositeAction.setEnabled(true); } } private String greeting; private JTextArea textArea; private Action oppositeAction; }
The COMMAND Pattern [15/55] |
The COMMAND Pattern [16/55] |
The COMMAND Pattern [17/55] |
The COMMAND Pattern [18/55] |
Name in
Design Pattern |
Actual Name
(Swing actions) |
Command |
Action |
ConcreteCommand |
subclass of AbstractAction |
execute() |
actionPerformed() |
state |
name and icon |
Factory Methods [19/55] |
The FACTORY METHOD Pattern [20/55] |
The FACTORY METHOD Pattern [21/55] |
The FACTORY METHOD Pattern [22/55] |
The FACTORY METHOD Pattern [23/55] |
Name in
Design Pattern |
Actual Name
(iterator) |
Creator |
Collection |
ConcreteCreator |
A subclass of Collection |
factoryMethod() |
iterator() |
Product |
Iterator |
ConcreteProduct |
A subclass of Iterator
(which is often anonymous) |
Not a FACTORY METHOD [24/55] |
Proxies [25/55] |
Deferred Image Loading [26/55] |
Deferred Image Loading [27/55] |
Proxies [28/55] |
file:horstmann/ch10_proxy/ImageProxy.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package horstmann.ch10_proxy; import java.awt.Component; import java.awt.Graphics; import javax.swing.Icon; import javax.swing.ImageIcon; /** A proxy for delayed loading of image icons. */ public class ImageProxy implements Icon { /** Constructs a proxy for delayed loading of an image file. @param name the file name */ public ImageProxy(String name) { this.name = name; image = null; } public void paintIcon(Component c, Graphics g, int x, int y) { ensureImageLoaded(); image.paintIcon(c, g, x, y); } public int getIconWidth() { ensureImageLoaded(); return image.getIconWidth(); } public int getIconHeight() { ensureImageLoaded(); return image.getIconHeight(); } /** Loads the image if it hasn't been loaded yet. Prints a message when the image is loaded. */ private void ensureImageLoaded() { if (image == null) { System.out.println("Loading " + name); image = new ImageIcon(name); } } private String name; private ImageIcon image; }
file:horstmann/ch10_proxy/ProxyTester.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package horstmann.ch10_proxy; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTabbedPane; /** This program demonstrates the use of the image proxy. Images are only loaded when you press on a tab. */ public class ProxyTester { public static void main(String[] args) { JTabbedPane tabbedPane = new JTabbedPane(); for (String name : imageNames) { JLabel label = new JLabel(new ImageProxy(name)); tabbedPane.add(name, label); } JFrame frame = new JFrame(); frame.add(tabbedPane); frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static final String[] imageNames = { "devonian.gif", "permian.gif", "jurassic1.gif", "jurassic2.gif", "cretaceous1.gif", "cretaceous2.gif", "cretaceous3.gif", "eocene1.gif", "eocene2.gif", "oligocene.gif", "miocene.gif", "pleistocene.gif" }; private static final int FRAME_WIDTH = 500; private static final int FRAME_HEIGHT = 300; }
The PROXY Pattern [29/55] |
The PROXY Pattern [30/55] |
The PROXY Pattern [31/55] |
The PROXY Pattern [32/55] |
Name in
Design Pattern |
Actual Name
(image proxy) |
Subject |
Icon |
RealSubject |
ImageIcon |
Proxy |
ImageProxy |
request() |
The methods of the Icon
interface type |
Client |
JLabel |
Singletons [33/55] |
Random Number Generator Singleton [34/55] |
public class SingleRandom
The SINGLETON Pattern [35/55] |
The SINGLETON Pattern [36/55] |
Not a SINGLETON [37/55] |
Inflexible Hierarchies [38/55] |
Inflexible Hierarchies [39/55] |
Visitors [40/55] |
Visitors [41/55] |
Visitors [42/55] |
Double Dispatch [43/55] |
Visitor Example [44/55] |
Visitor Example [45/55] |
Visitor Example [46/55] |
Visitor Example [47/55] |
file:horstmann/ch10_visitor/FileSystemNode.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
package horstmann.ch10_visitor; /** The common interface for file and directory nodes. */ public interface FileSystemNode { void accept(FileSystemVisitor v); }
file:horstmann/ch10_visitor/FileNode.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package horstmann.ch10_visitor; import java.io.File; public class FileNode implements FileSystemNode { public FileNode(File file) { this.file = file; } public File getFile() { return file; } public void accept(FileSystemVisitor v) { v.visitFileNode(this); } private File file; }
file:horstmann/ch10_visitor/DirectoryNode.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package horstmann.ch10_visitor; import java.io.File; public class DirectoryNode implements FileSystemNode { public DirectoryNode(File directory) { this.directory = directory; } public void accept(FileSystemVisitor v) { v.visitDirectoryNode(this); } public File getDirectory() { return directory; } public FileSystemNode[] getChildren() { File[] files = directory.listFiles(); FileSystemNode[] children = new FileSystemNode[files.length]; for (int i = 0; i < files.length; i++) { File f = files[i]; if (f.isDirectory()) children[i] = new DirectoryNode(f); else children[i] = new FileNode(f); } return children; } private File directory; }
file:horstmann/ch10_visitor/FileSystemVisitor.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package horstmann.ch10_visitor; /** The visitor interface type for visiting file system nodes. */ public interface FileSystemVisitor { /** Visits a file node. @param node the file node */ void visitFileNode(FileNode node); /** Visits a directory node. @param node the directory node */ void visitDirectoryNode(DirectoryNode node); }
file:horstmann/ch10_visitor/PrintVisitor.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
package horstmann.ch10_visitor; public class PrintVisitor implements FileSystemVisitor { public void visitFileNode(FileNode node) { for (int i = 0; i < level; i++) System.out.print(" "); System.out.println(node.getFile().getName()); } public void visitDirectoryNode(DirectoryNode node) { for (int i = 0; i < level; i++) System.out.print(" "); System.out.println(node.getDirectory().getName()); level++; for (FileSystemNode c : node.getChildren()) c.accept(this); level--; } private int level = 0; }
file:horstmann/ch10_visitor/VisitorTester.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
package horstmann.ch10_visitor; import java.io.File; public class VisitorTester { public static void main(String[] args) { DirectoryNode node = new DirectoryNode(new File("..")); node.accept(new PrintVisitor()); } }
Double Dispatch Example [48/55] |
Double Dispatch Example [49/55] |
The VISITOR Pattern [50/55] |
The VISITOR Pattern [51/55] |
The VISITOR Pattern [52/55] |
The VISITOR Pattern [53/55] |
Name in
Design Pattern |
Actual Name (file system
visitor) |
Element |
FileSystemNode |
ConcreteElement |
FileNode, DirectoryNode |
Visitor |
FileSystemVisitor |
ConcreteVisitor |
PrintVisitor |
Other Design Patterns [54/55] |
Conclusion: What You Learned [55/55] |
Revised: 2007/09/11 16:42