chapter 3 adapter summary prepared by kirk scott 1

151
Chapter 3 Adapter Summary prepared by Kirk Scott 1

Upload: ruby-kirt

Post on 15-Dec-2015

229 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Chapter 3 Adapter Summary prepared by Kirk Scott 1

1

Chapter 3Adapter

Summary prepared by Kirk Scott

Page 2: Chapter 3 Adapter Summary prepared by Kirk Scott 1

2

WhimbrelFrom Wikipedia, the free encyclopedia

• The Whimbrel (Numenius phaeopus) is a wader in the large family Scolopacidae. It is one of the most widespread of the curlews, breeding across much of subarctic North America, Europe and Asia as far south as Scotland.

• This is a migratory species wintering on coasts in Africa, South America, south Asia into Australasia and southern North America. It is also a coastal bird during migration.[2] It is fairly gregarious outside the breeding season.

Page 3: Chapter 3 Adapter Summary prepared by Kirk Scott 1

3

Page 4: Chapter 3 Adapter Summary prepared by Kirk Scott 1

4

GodwitFrom Wikipedia, the free encyclopedia

• Jump to: navigation, search For other uses, see Limosa (disambiguation).

• The godwits are a group of large, long-billed, long-legged and strongly migratory waders of the bird genus Limosa. Their long, bills allow them to probe deeply in the sand for aquatic worms and molluscs. They frequent tidal shorelines, breeding in northern climates in summer and migrating south in winter. In their winter range, they flock together where food is plentiful. A female Bar-tailed Godwit holds the record for the longest non-stop flight for a land bird.[1]

Page 5: Chapter 3 Adapter Summary prepared by Kirk Scott 1

5

• They can be distinguished from the curlews by their straight or slightly upturned bills, and from the dowitchers by their longer legs. The winter plumages are fairly drab, but three species have reddish underparts when breeding. The females are appreciably larger than the males.

• Although not common tablefare today, they were once a popular British dish. Sir Thomas Browne writing in the seventeenth century noted that godwits "were accounted the daintiest dish in England."

• The name Godwit originates in Old English with god meaning good, and wit coming from wihte, meaning creature.[2]

Page 6: Chapter 3 Adapter Summary prepared by Kirk Scott 1

6

Page 7: Chapter 3 Adapter Summary prepared by Kirk Scott 1

7

Page 8: Chapter 3 Adapter Summary prepared by Kirk Scott 1

8

CurlewFrom Wikipedia, the free encyclopedia

• Jump to: navigation, search For other uses, see Curlew (disambiguation).For other uses of "Numenius", see Numenius.

• The curlews /ˈkɜrljuːz/, genus Numenius, are a group of eight species of birds, characterised by long, slender, downcurved bills and mottled brown plumage. They are one of the most ancient lineages of scolopacid waders, together with the godwits which look similar but have straight bills.[1] In Europe "curlew" usually refers to one species, the Eurasian Curlew Numenius arquata.

Page 9: Chapter 3 Adapter Summary prepared by Kirk Scott 1

9

Page 10: Chapter 3 Adapter Summary prepared by Kirk Scott 1

10

Design Patterns in JavaChapter 3Adapter

Summary prepared by Kirk Scott

Page 11: Chapter 3 Adapter Summary prepared by Kirk Scott 1

11

Introduction Before the Introduction

• The adapter design pattern is fundamental• One of my jokes is that once you’ve seen the

adapter pattern, every pattern after it can be described as a kind of adapter

• The pattern allows one class to “make use of” another

Page 12: Chapter 3 Adapter Summary prepared by Kirk Scott 1

12

• Structurally, there are two different implementations of the pattern

• The Class Adapter is based on an interface and a subclass

• The Object Adapter is based on a subclass and a wrapped instance of another class

Page 13: Chapter 3 Adapter Summary prepared by Kirk Scott 1

13

Introduction to the Class Adapter

• Consider these possible scenarios in the development of client and service code which need to work together

• The client and service code may simply be written independently, without (advance) knowledge of each other’s interfaces

• Or, the client code may be written before the service code

Page 14: Chapter 3 Adapter Summary prepared by Kirk Scott 1

14

• Or, code bases may belong to different organizations which happen to define different interfaces for the same functionality

• In any of these scenarios, the client code may make calls to methods that do not end up in the service code

Page 15: Chapter 3 Adapter Summary prepared by Kirk Scott 1

15

• The ultimate goal is for the client and server to work together in spite of the mismatch

• In order for this to happen, at the very least the needed functionality has to exist in the service code, even if it is behind a different interface

Page 16: Chapter 3 Adapter Summary prepared by Kirk Scott 1

16

• You may consider rewriting either the client or the service code so that their naming conventions match

• However, this may not be possible for political or timing reasons

• Even if possible, recoding may be undesirable because it’s too much work

Page 17: Chapter 3 Adapter Summary prepared by Kirk Scott 1

17

• In a situation like this, the adapter pattern can be used

• By insightful use of interfaces and subclasses, adding one class to the system makes it possible for the client code base to use the service code base

Page 18: Chapter 3 Adapter Summary prepared by Kirk Scott 1

18

Book Definition of Pattern

• Book definition:• The intent of Adapter is to provide the

interface that a client expects while using the services of a class with a different interface

Page 19: Chapter 3 Adapter Summary prepared by Kirk Scott 1

19

The Class Adapter: Adapting to an Interface

• In the ideal case, client and service code are simply written to be consistent with each other

• If the client code is written first, the client developer may create an interface which defines all of the calls the client will need to make

• Then the service code developer can have the service classes implement that interface

Page 20: Chapter 3 Adapter Summary prepared by Kirk Scott 1

20

• In the less than ideal case, the service code is not written to the desired interface

• However, such an interface, defining what the client needs, can be used to apply the class adapter design pattern

• The adapter class, which connects the client with the service code, will implement this interface

Page 21: Chapter 3 Adapter Summary prepared by Kirk Scott 1

21

• The adapter class will also extend the class in the service code base which contains the useful methods

• The implementation of the interface methods in the adapter class are based on calls to the useful, but “misnamed” methods inherited from the superclass in the service code base

Page 22: Chapter 3 Adapter Summary prepared by Kirk Scott 1

22

• The diagram on the following overhead illustrates a class adapter

• Note that for this pattern a UML diagram can be given right away

• The pattern is immediately apparent from the diagram

Page 23: Chapter 3 Adapter Summary prepared by Kirk Scott 1

23

Page 24: Chapter 3 Adapter Summary prepared by Kirk Scott 1

24

• The client makes use of an interface, RequiredInterface, which specifies a method named requiredMethod()

• The service code contains a class, ExistingClass with a method named usefulMethod(), which contains the needed functionality

• The NewClass is the adapter, which implements the interface and extends ExistingClass

• The implementation of requiredMethod() in NewClass is based on calls to usefulMethod() in ExistingClass

Page 25: Chapter 3 Adapter Summary prepared by Kirk Scott 1

25

Using the Class Adapter in Practice

• Before moving on, there is another aspect of this to consider

• In the diagram, the client is shown as making use of the interface by means of a solid line with an open arrowhead

• This notation in UML can mean that the client has an instance variable of the type referred to

Page 26: Chapter 3 Adapter Summary prepared by Kirk Scott 1

26

• This notation can also mean that the client has a reference to something with that type which isn’t an instance variable

• For example, the client may have a parameter of that typed passed to it

Page 27: Chapter 3 Adapter Summary prepared by Kirk Scott 1

27

Interface References to Objects

• Either way, the critical idea is this:• The client code is written with references to

the interface, not references to specific classes• An object of any class that implements the

interface can be passed to the client and used by it

Page 28: Chapter 3 Adapter Summary prepared by Kirk Scott 1

28

• This is a simple, but very important idea• In CS 202 you learn about superclass

references to subclass objects• Here you are seeing interface references to

objects of classes that implement the interface

Page 29: Chapter 3 Adapter Summary prepared by Kirk Scott 1

29

Implementation of Adapter Methods

• The client will be written to call the method requiredMethod(), but not on a direct reference to a NewClass object

• The client will be written to call the method requiredMethod() in this way:

• requiredInterfaceReference.requiredMethod()

Page 30: Chapter 3 Adapter Summary prepared by Kirk Scott 1

30

A More Concrete Example

• The book gives an example of a class adapter using rockets

• The example will center on two methods relevant to the performance of rockets during flight, getMass() and getThrust()

• The mass and thrust of a rocket are dependent on time

• Over the course of a flight, as fuel is burnt, mass goes down, and at some point the rocket achieves maximum thrust

Page 31: Chapter 3 Adapter Summary prepared by Kirk Scott 1

31

The Structure of the Example

• The example begins with two parts:• EventSim, a rocket simulation program, the

client• RocketSim, the interface for rockets used by

the client• A UML diagram for this is shown on the

following overhead

Page 32: Chapter 3 Adapter Summary prepared by Kirk Scott 1

32

Page 33: Chapter 3 Adapter Summary prepared by Kirk Scott 1

33

• The example also has a PhysicalRocket class which represents rockets

• The goal is to run EventSim and apply it to instances of the PhysicalRocket class

• The PhysicalRocket class methods are not exactly the same as the methods in the RocketSim interface

Page 34: Chapter 3 Adapter Summary prepared by Kirk Scott 1

34

• The methods in the class PhysicalRocket parallel the functionality of the methods in the RocketSim interface

• The names of the methods in the interface and the class are the same, but their parameter lists differ

• The PhysicalRocket class has to be adapted to the RocketSim interface

Page 35: Chapter 3 Adapter Summary prepared by Kirk Scott 1

35

• The PhysicalRocket class is adapted to the RocketSim interface in this way:

• You write a new, adapter class, OozinozRocket, which implements the interface and extends the class.

• The book does this in steps, as a challenge• The UML diagram on the following overhead

cuts to the chase

Page 36: Chapter 3 Adapter Summary prepared by Kirk Scott 1

36

Challenge 3.1 Solution

Page 37: Chapter 3 Adapter Summary prepared by Kirk Scott 1

37

• The adapter class has to deal with the mismatch in the specifications between the adapter interface and the class to be adapted

• The getMass() and getThrust() methods take no parameter in the RocketSim interface

• They take a time parameter in the PhysicalRocket class

Page 38: Chapter 3 Adapter Summary prepared by Kirk Scott 1

38

• There is a setSimTime() method in the RocketSim interface

• RocketSim keeps an internal clock and occasionally updates simulated objects by calling the setSimTime() method

• The adapter class implements this method and provides the instance variable needed for it

Page 39: Chapter 3 Adapter Summary prepared by Kirk Scott 1

39

• This instance variable makes it possible for the adapter to make use of the base class methods

• An adapter method which doesn’t take a time parameter is implemented by calling a service class method that does take a time parameter

• The adapter method passes in the time instance variable when calling the service class method

Page 40: Chapter 3 Adapter Summary prepared by Kirk Scott 1

40

• The adapter class, OoozinozRocket, inherits methods from the PhysicalRocket class

• These inherited methods are used in implementing the interface methods

• The following overheads show the code solution for the adapter class

• As usual, the book does this as a challenge• The solution is simply presented here

Page 41: Chapter 3 Adapter Summary prepared by Kirk Scott 1

41

Solution 3.2

• package com.oozinoz.firework;• import com.oozinoz.simulation.*;• public class OozinozRocket• extends PhysicalRocket• implements RocketSim• {• /*** The adapter class has this instance variable. ***/

• private double time;

Page 42: Chapter 3 Adapter Summary prepared by Kirk Scott 1

42

• public OozinozRocket• (double burnArea, double burnRate,• double fuelMass, double totalMass)• {• super(burnArea, burnRate,• fuelMass, totalMass);• }• /*** The adapter class also has this set method

for the needed variable. ***/• public void setSimTime(double time)• {• this.time = time;• }

Page 43: Chapter 3 Adapter Summary prepared by Kirk Scott 1

43

• /*** With the variable available, it’s a piece of cake to implement these methods. ***/

• public double getMass()• {• return getMass(time);• }• public double getThrust()• {• return getThrust(time);• }

Page 44: Chapter 3 Adapter Summary prepared by Kirk Scott 1

44

More Comments on the Code

• The time instance variable provides the parameter needed in order to call the service class methods

• It is apparent that the client side developer, when specifying the interface, knew that a time variable would be necessary

• That accounts for the inclusion of setSimTime() in the interface

Page 45: Chapter 3 Adapter Summary prepared by Kirk Scott 1

45

• Both getMass() and getThrust() are overloaded in the Adapter class

• The class inherits the versions which take parameters and implements the versions which don’t

Page 46: Chapter 3 Adapter Summary prepared by Kirk Scott 1

46

• The interface versions of the methods don’t have a time parameter

• The client code only calls these versions• The service code versions of the methods do

have a time parameter• In the adapter class code, a call to the service

method—with a time parameter—is wrapped inside the implementation of the interface version of the method

Page 47: Chapter 3 Adapter Summary prepared by Kirk Scott 1

47

Simplicity/Complexity

• The example is simple• It’s so simple that you may overlook what is

happening• When you call one version of a method, that is

delegated to another version of the same method

• The call is passed on, and that call is made on the implicit parameter

Page 48: Chapter 3 Adapter Summary prepared by Kirk Scott 1

48

• The adapter for the client side has get methods that don’t take a time parameter

• They assume that the needed time is passed in with a call to setSimTime()

• The service class actually has methods that take the needed time parameter

Page 49: Chapter 3 Adapter Summary prepared by Kirk Scott 1

49

• You might think if mass and thrust depend on time, then the client side code might have been written with method calls which passed time as a parameter

• But setting the simulation time separately is an equally valid way of making the time available

Page 50: Chapter 3 Adapter Summary prepared by Kirk Scott 1

50

• If time is made available in this way, then in the client code:

• You would have to pay careful attention to when you had called setSimTime() before calling either getMass() or getThrust()

• The return values of the get calls will depend on the most recent value of simTime that was sent in

Page 51: Chapter 3 Adapter Summary prepared by Kirk Scott 1

51

Introduction to the Object Adapter

• Suppose that the client code base does not specify a particular interface

• Instead, it has been coded to use the methods of a particular class

• Suppose that a different class exists in the service code which provides the necessary functionality

Page 52: Chapter 3 Adapter Summary prepared by Kirk Scott 1

52

• An object adapter is a class which extends the class specified in the client and wraps an instance of the service class

• The adapter derives the needed functionality from the wrapped instance

• In other words, the methods in the adapter class work by calling methods on the wrapped object

Page 53: Chapter 3 Adapter Summary prepared by Kirk Scott 1

53

• This way of doing things is expressed by the term “delegation”

• The object adapter delegates responsibility for the actual functionality desired to the instance of the service class it contains

• The adapter class adapts an instance of the service class for use by the client by providing an appropriate interface for it

Page 54: Chapter 3 Adapter Summary prepared by Kirk Scott 1

54

• The diagram on the following overhead illustrates an object adapter

• Note that for this pattern, just like for a class adapter, a UML diagram can be given right away

• The pattern is immediately apparent from the diagram

Page 55: Chapter 3 Adapter Summary prepared by Kirk Scott 1

55

Page 56: Chapter 3 Adapter Summary prepared by Kirk Scott 1

56

• The adapter class is connected to the useful class by means of a navigability arrow

• The adapter class contains a reference to a useful class instance variable

• The adapter class implements the interface needed by the client

• It does so by making calls to methods on the useful object

Page 57: Chapter 3 Adapter Summary prepared by Kirk Scott 1

57

• The form of delegation in the adapter class is illustrated by this snippet of code:

• requiredMethod()• {• …• existingClassObjectReference.usefulMethod();• …• }

Page 58: Chapter 3 Adapter Summary prepared by Kirk Scott 1

58

• The structures of the class and object adapters are not the same

• However, both are valid adapters• Their intent and functional effect are the same

Page 59: Chapter 3 Adapter Summary prepared by Kirk Scott 1

59

A More Concrete Example

• Suppose that the EventSim client is coded to work directly with references to objects of a class named Skyrocket

• The Skyrocket class has methods getMass(), getThrust() which do not take a time parameter

• It also has a setSimTime() method• The UML diagram shown on the following

overhead illustrates this idea

Page 60: Chapter 3 Adapter Summary prepared by Kirk Scott 1

60

UML for the Client Side

Page 61: Chapter 3 Adapter Summary prepared by Kirk Scott 1

61

The Service Side of the Example

• The service side of the application is similar to the previous scenario

• There is a PhysicalRocket class that implements the desired functionality

• You want to use the methods of the PhysicalRocket class to support the functionality of the methods of the Skyrocket class on the client side

Page 62: Chapter 3 Adapter Summary prepared by Kirk Scott 1

62

The Adapter Class

• The adapter class will be a subclass of the client side SkyRocket class

• The adapter class will have a PhysicalRocket instance variable

• The adapter class will override the methods, delegating to the PhysicalRocket it contains

Page 63: Chapter 3 Adapter Summary prepared by Kirk Scott 1

63

• As usual, the book does things in stages• The UML diagram given on the next overhead

shows the book’s complete design

Page 64: Chapter 3 Adapter Summary prepared by Kirk Scott 1

64

Solution 3.4

Page 65: Chapter 3 Adapter Summary prepared by Kirk Scott 1

65

Things to Note in the Diagram

• You might note that if there were such a thing, multiple inheritance would be an approach to solving the problem

• In the class adapter you implement an interface on the client side and extend a class on the service side

• Here, you extend a class on the client side• You can’t also extend the class on the service side• Instead, you have to wrap an instance

Page 66: Chapter 3 Adapter Summary prepared by Kirk Scott 1

66

• The simulation time variable, as in the class adapter example, is at the heart of what you will have to do in your implementation

• In the SkyRocket class there is a double instance variable simTime and a setSimTime() method

• In this example these are inherited by the adapter subclass

Page 67: Chapter 3 Adapter Summary prepared by Kirk Scott 1

67

• The simTime variable is marked with a # sign, meaning that it’s declared protected

• That means that the adapter subclass will have direct access to its own simTime instance variable without calling a get method

• This is not a design decision that I would prefer

• It will be discussed further later on

Page 68: Chapter 3 Adapter Summary prepared by Kirk Scott 1

68

Code for the Object Adapter Example

• The object adapter class has to obtain a reference to a PhysicalRocket object

• The object adapter class also has to override getMass() and getThrust()

• The book’s code is presented on the following overheads with commentary

Page 69: Chapter 3 Adapter Summary prepared by Kirk Scott 1

69

The beginning of the OozinozSkyrocket class code.

• package com.oozinoz.firework;• import com.oozinoz.simulation.*;• public class OozinozSkyrocket• extends Skyrocket• {• private PhysicalRocket rocket;

Page 70: Chapter 3 Adapter Summary prepared by Kirk Scott 1

70

The book’s constructor for the subclass, which relies on an instance of the PhysicalRocket class being passed in

• public OozinozSkyrocket(PhysicalRocket r)• {• super(r.getMass(0);• r.getThrust(0);• r.getBurnTime());• rocket = r;• }

Page 71: Chapter 3 Adapter Summary prepared by Kirk Scott 1

71

• The constructor for the object adapter relies on a call to super in the superclass on the client side, Skyrocket

• The superclass constructor requires values for mass and thrust

• This is the first example of wrapping• The needed values are acquired by calling getMass() and

getThrust() on the input parameter, the PhysicalRocket• Because this is initialization, time t = 0 is used• The call to super has to come first• Then you can initialize the instance variable, r

Page 72: Chapter 3 Adapter Summary prepared by Kirk Scott 1

72

An Alternative Approach

• You could also write the constructor for the subclass to take in the construction parameters for a PhysicalRocket object

• Then the OozinozSkyrocket constructor would construct an instance of PhysicalRocket instead of receiving one as a parameter

• This is not better, just an alternative• One way or the other, the instance of the object

adapter class, OozinozSkyrocket, has to end up with a live PhysicalRocket reference inside it

Page 73: Chapter 3 Adapter Summary prepared by Kirk Scott 1

73

Using the Object Adapter in Practice

• The Object Adapter pattern works because of straightforward polymorphism

• You can have a superclass reference to a subclass object

• In the client code, a parameter would be typed to the superclass, Skyrocket, for example

• A reference to the adapter subclass, OozinozSkyrocket, could then be passed to the client code

Page 74: Chapter 3 Adapter Summary prepared by Kirk Scott 1

74

The method implementations in the OozinozSkyrocket object adapter class code

• public double getMass()• {• return rocket.getMass(simTime);• }• public double getThrust()• {• return rocket.getThrust(simTime);• }

Page 75: Chapter 3 Adapter Summary prepared by Kirk Scott 1

75

Compare the foregoing with the solution in the Class Adapter case:

• public double getMass()• {• return getMass(time);• }• public double getThrust()• {• return getThrust(time);• }

Page 76: Chapter 3 Adapter Summary prepared by Kirk Scott 1

76

• In the Class Adapter case you call methods inherited from the PhysicalRocket class on the implicit parameter in order to implement the adapter methods

• In the Object Adapter case, you call methods on an instance of the PhysicalRocket class in order to implement the adapter methods

• In both cases the conversion is from a method that takes a time parameter to one that doesn’t

Page 77: Chapter 3 Adapter Summary prepared by Kirk Scott 1

77

• Challenge 3.4• “Name one reason why the object adapter

design that the OozinozSkyrocket class uses may be more fragile than a class adapter approach.”

Page 78: Chapter 3 Adapter Summary prepared by Kirk Scott 1

78

• Solution 3.4• “The object adapter design that the

OozinozSkyrocket class uses may be more fragile than a class adapter approach for the following reasons.

• [see the following overheads]

Page 79: Chapter 3 Adapter Summary prepared by Kirk Scott 1

79

• [1] There is no specification of the interface that the OozinozSkyrocket class provides.

• As a result, the Skyrocket might change in ways that would create problems at runtime but go undetected at compile time.

• [Comments will follow.]

Page 80: Chapter 3 Adapter Summary prepared by Kirk Scott 1

80

• [2] The OozinozSkyrocket counts on being able to access the simTime variable of its parent class, although there is no guarantee that this variable will always be declared as protected and no guarantee about the meaning of this field in the Skyrocket class.

• (We don’t expect the providers to go out of their way to change the Skyrocket code we rely on, but on the other hand, we have limited control over what they do.)”

Page 81: Chapter 3 Adapter Summary prepared by Kirk Scott 1

81

Comments on Fragility Number 2

• Comment mode on:• I want to deal with “fragility” number 2 first:• This is the kind of nonsense that makes you want to

bellow in revulsion and disbelief• The instance variable should be declared private,

not protected• This has nothing to do with the design pattern, and

the fact that they identify this as a shortcoming is merely an argument against their own lame coding practices

Page 82: Chapter 3 Adapter Summary prepared by Kirk Scott 1

82

Comments on Fragility Number 1

• Regarding “fragility” number 1, the premise seems to be the following:

• In the class adapter pattern, you specify the desired interface

• Presumably, having made the specification, it is something that is unlikely to change

Page 83: Chapter 3 Adapter Summary prepared by Kirk Scott 1

83

• The authors assume that the specifications of the Skyrocket class may be subject to change

• On the one hand, you might ask whether this is more changeable than an interface

• At any rate, they then observe that the changes might cause problems that the compiler wouldn’t catch and which would only be evident at run time

Page 84: Chapter 3 Adapter Summary prepared by Kirk Scott 1

84

• How might this happen?• The superclass has its instance variables and

methods changed• The subclass inherits all of the changes, but—• It still includes the methods developed earlier• These methods may still override methods in the

superclass• If the superclass methods are gone, then the

methods in the subclass are simply independent

Page 85: Chapter 3 Adapter Summary prepared by Kirk Scott 1

85

• The bottom line is that the set of methods in the subclass may no longer appropriately perform adaptation

• The fundamental moral of the story is this:• If you develop a hierarchy of classes and you

make a change in a superclass, you need to trace down through all of its subclasses to see whether or not they are still OK

Page 86: Chapter 3 Adapter Summary prepared by Kirk Scott 1

86

• This fundamental design and coding principle applies whether you’re talking about adapters or not

• If you can safely assume that a specified interface is unlikely to change, then the class adapter pattern is not liable to this problem

• On the other hand, if the interface specification does change, you face a similar situation

Page 87: Chapter 3 Adapter Summary prepared by Kirk Scott 1

87

• You would have to look at every class that implemented the interface to make sure that the implementation matched the new specification

• The difference is that the compiler would detect classes that declared that they implemented the interface but which no longer conformed to the interface specifications

Page 88: Chapter 3 Adapter Summary prepared by Kirk Scott 1

88

Final Methods and Adaptation

• The book makes another observation about the applicability of the object adapter

• If one of the methods in the client superclass had been declared final it couldn’t be overridden in a subclass

• Then the the object adapter approach wouldn’t work

• There are always potential problems• Dirty Harry says, “Know your limitations.”

Page 89: Chapter 3 Adapter Summary prepared by Kirk Scott 1

89

Choosing between Class and Object Adapters

• The book suggests that the class adapter is preferable to the object adapter

• However, you do what you have to do• If no client interface is given, the object

adapter approach works• The next example will illustrate a situation

where object adaptation is the correct approach for several reasons

Page 90: Chapter 3 Adapter Summary prepared by Kirk Scott 1

90

Are Java Adapter Classes the Same as the Adapter Design Pattern?

• The answer to this question is basically “no”• The book covers it in some detail, and for

what it’s worth, that treatment is repeated here

• Consider the UML diagram for the Java MouseAdapter class on the following overhead, and the challenge that follows it

Page 91: Chapter 3 Adapter Summary prepared by Kirk Scott 1

91

Page 92: Chapter 3 Adapter Summary prepared by Kirk Scott 1

92

• Challenge 3.6• “Are you applying the Adapter pattern when

you use the MouseAdapter class? Explain how (or why not).”

Page 93: Chapter 3 Adapter Summary prepared by Kirk Scott 1

93

• Solution 3.6• “One argument: When the user clicks the

mouse, I need to translate, or adapt, the resulting Swing call into an appropriate action.

• In other words, when I need to adapt GUI events to my application’s interface, I use Swing adapter classes.

• I am translating from one interface to another, fulfilling the intent of the Adapter pattern.

Page 94: Chapter 3 Adapter Summary prepared by Kirk Scott 1

94

• A counterargument: The “adapter” classes in Swing are stubs:

• They don’t translate or adapt anything. • You subclass these classes, overriding the methods

you need to do something. • If anything, it is your methods and your class that

form an example of Adapter. • Had the Swing “adapter” been named something

like DefaultMouseListener, this argument never would have arisen.”

Page 95: Chapter 3 Adapter Summary prepared by Kirk Scott 1

95

• On the following overhead a UML diagram is given

• It may be helpful in understanding the foregoing discussion.

Page 96: Chapter 3 Adapter Summary prepared by Kirk Scott 1

96

Page 97: Chapter 3 Adapter Summary prepared by Kirk Scott 1

97

Another Example

• In the units so far “Another Example” has been something developed by me with cups and seeds or something like that

• In this unit the other example is taken from the chapter in the book

• This is another example (like façade) where the book identifies the use of a design pattern in the Java API

Page 98: Chapter 3 Adapter Summary prepared by Kirk Scott 1

98

The Scenario

• The scenario involves displaying data in tabular form• An application may contain instances of a given

class• That class would have a set of instance variables• This would be a logical way of displaying

information about objects of the class:• Create a table with one row for each object• The columns would contain the values of the

instance variables for each object

Page 99: Chapter 3 Adapter Summary prepared by Kirk Scott 1

99

• This is a small example of a table containing information about specific kinds of rockets

Page 100: Chapter 3 Adapter Summary prepared by Kirk Scott 1

100

Adapting Data for a JTable

• The machinery in the Java API for the application of the adapter design pattern to this scenario includes these components:

• The client class: JTable• An interface: TableModel• An abstract class: AbstractTableModel

Page 101: Chapter 3 Adapter Summary prepared by Kirk Scott 1

101

JTable

• JTable is the basic building block in the Java API for the use of the pattern

• JTable contains the functionality for displaying data in tabular form

• You would write an application that created and used a JTable, relying on JTable to display the table

Page 102: Chapter 3 Adapter Summary prepared by Kirk Scott 1

102

• JTable is not the adapter in this example• JTable is the client, and the application

containing it is the client of the client, so to speak

• You need the adapter pattern to adapt instances of the class to be displayed as sources for input to a JTable

Page 103: Chapter 3 Adapter Summary prepared by Kirk Scott 1

103

An Interface: TableModel

• The application of the adapter pattern in the Java API involves the use of an interface, TableModel

• However, this example illustrates object adaptation, not class adaptation

• There is an interface because the application of the pattern is slightly more complicated than the initial examples of adaptation given earlier

Page 104: Chapter 3 Adapter Summary prepared by Kirk Scott 1

104

An Abstract Class: AbstractTableModel

• There is also an abstract class in the application of the pattern

• This did not exist in either of the two simple examples of adaptation

• The AbstractTableModel class is provided as a superclass for concrete classes which will be the adapters for object adaptation

Page 105: Chapter 3 Adapter Summary prepared by Kirk Scott 1

105

UML for Table Adaptation

• On the following three overheads a sequence of UML diagrams is given

• This sequence traces the example from the JTable class, the client, through the interface and abstract class to the following:

• A concrete RocketTableModel adapter class, a subclass of the AbstractTableModel class

Page 106: Chapter 3 Adapter Summary prepared by Kirk Scott 1

106

• The RocketTableModel class is an object adapter

• It contains an array of references to instances of the Rocket class

• It is the data for individual rockets whose data should populate the table

• The RocketTableModel class does object adaptation of rocket objects to the requirements for a row in a table

Page 107: Chapter 3 Adapter Summary prepared by Kirk Scott 1

107

Page 108: Chapter 3 Adapter Summary prepared by Kirk Scott 1

108

Page 109: Chapter 3 Adapter Summary prepared by Kirk Scott 1

109

Page 110: Chapter 3 Adapter Summary prepared by Kirk Scott 1

110

JTable, Again

• The class JTable is designed to display information in tables

• The JTable class was written to accept as input things that implement the TableModel interface

Page 111: Chapter 3 Adapter Summary prepared by Kirk Scott 1

111

TableModel, Again

• The TableModel interface defines the set of methods which a class should have in order to be displayable in a JTable

• Rather than putting the specifications for the adapting class into a class, the Java API designers put them into an interface

Page 112: Chapter 3 Adapter Summary prepared by Kirk Scott 1

112

AbstractTableModel, Again

• The AbstractTableModel implements the TableModel interface

• To use JTable the programmer has to write a concrete class that extends AbstractTableModel

• JTable will make use of instances of this concrete class wherever it has references to the TableModel interface

Page 113: Chapter 3 Adapter Summary prepared by Kirk Scott 1

113

• The concrete class that extends AbstractTableModel is an object adapter

• It should contain and adapt one or more references to base objects which are to be displayed in the table

Page 114: Chapter 3 Adapter Summary prepared by Kirk Scott 1

114

Why Object Adaptation?

• There are several reasons for using an object adapter arrangement like this for tables

• 1. It’s convenient to have the AbstractTableModel class on the client side instead of an interface

• This makes it possible to provide default implementations of methods

Page 115: Chapter 3 Adapter Summary prepared by Kirk Scott 1

115

• Only if necessary will those methods be overridden in the concrete subclass

• Notice how this is in general a direct argument in favor of object adaptation

• In a previous section object adaptation was criticized as fragile

• In its favor, it does support inheritance rather than implementation from scratch for an interface

Page 116: Chapter 3 Adapter Summary prepared by Kirk Scott 1

116

• 2. There is a second reason why object adaptation might be better than class adaptation in some situations

• This has to do with a fundamental question in object-oriented design

• The example does class adaptation between tables and rockets

Page 117: Chapter 3 Adapter Summary prepared by Kirk Scott 1

117

• We will have a class, RocketAdapter, which implements the TableModelInterface and extends the Rocket class

• Even though RocketAdapter extends the Rocket class, implementing the interface turns out to be the defining characteristic of the adapter

Page 118: Chapter 3 Adapter Summary prepared by Kirk Scott 1

118

• Client code only calls adapter interface methods on objects of the adapter class

• The client doesn’t call rocket specific methods on those objects, even though they inherit them

• Any calls that do involve rocket specific features are delegated through interface calls

Page 119: Chapter 3 Adapter Summary prepared by Kirk Scott 1

119

• From the client code’s perspective, the adapter quacks like a table model and walks like a table model

• In other words, in a sense the adapter class becomes “a kind of” the TableModel, not a kind of rocket

• Rational object-oriented design says that if something is no longer a kind of something else, then structurally, it shouldn’t be a subclass of that other class

Page 120: Chapter 3 Adapter Summary prepared by Kirk Scott 1

120

• Therefore, if you were using the class adapter version of the pattern it would not be logically desirable for the class that implemented the interface to be a subclass of the Rocket class

• The logical alternative is to use the object adapter version of the pattern

Page 121: Chapter 3 Adapter Summary prepared by Kirk Scott 1

121

• The Java API does use object adaptation• In the example, the adapter is named

RocketTableModel• It is not named RocketAdapter• This is because the adapter has more to do

with tables than with rockets

Page 122: Chapter 3 Adapter Summary prepared by Kirk Scott 1

122

Why Object Adaptation, Again

• Everything said above could be said to apply more or less in general

• Whether object adaptation is really preferable depends on the problem domain

• In the initial example it was a rocket simulator and rockets

• There it seemed perfectly logical for the simulator to work with adapted rockets

Page 123: Chapter 3 Adapter Summary prepared by Kirk Scott 1

123

• With tables, the difference between JTable and rocket is great

• Here it makes sense for the client to work not with rockets, but with an adapter which is really a table model

• The table model essentially wraps the “foreign” item, rocket, completely, and JTable only has to worry about generic things like data items, not specific rocket attributes

Page 124: Chapter 3 Adapter Summary prepared by Kirk Scott 1

124

Specifics on AbstractTableModel

• The Java API contains the abstract class, AbstractTableModel

• This class includes default implementations of most of the methods in the TableModel interface

• The Java API is trying to do some of the work for the programmer wanting to use JTable

Page 125: Chapter 3 Adapter Summary prepared by Kirk Scott 1

125

• A UML diagram of the AbstractTableModel class is shown on the following overhead

• This shows the three methods that a concrete subclass has to override: – public int getRowCount();– public int getColumnCount();– public Object getValueAt(int row, int column);

Page 126: Chapter 3 Adapter Summary prepared by Kirk Scott 1

126

Page 127: Chapter 3 Adapter Summary prepared by Kirk Scott 1

127

• The implementation of the methods depends on what is being adapted

• In particular, these methods presuppose that the adapter has references to multiple objects with multiple attributes

Page 128: Chapter 3 Adapter Summary prepared by Kirk Scott 1

128

• The row count would depend on how many rockets the adapter had a reference to

• The column count would depend on how many of the attributes of a rocket were to be displayed in the table

• getValueAt() would obtain the contents of a cell of the table

Page 129: Chapter 3 Adapter Summary prepared by Kirk Scott 1

129

Specifics of RocketTableModel

• The RocketTableModel class is the programmer written adapter class in this example

• It extends the AbstractTableModel class• The RocketTableModel class implements the

three needed methods• It also implements a getColumnName() method,

among other things• The UML diagram showing this is shown again on

the following overhead

Page 130: Chapter 3 Adapter Summary prepared by Kirk Scott 1

130

Page 131: Chapter 3 Adapter Summary prepared by Kirk Scott 1

131

• The RocketTableModel has an instance variable which is an array of rockets

• A constructor is shown for the RocketTableModel class which takes an array of rockets as an input parameter

• Each element of the rocket array will become a row in the table

• Each column in a row will take its value from one of the instance variables of a rocket

Page 132: Chapter 3 Adapter Summary prepared by Kirk Scott 1

132

• The RocketTableModel also has an instance variable which is an array of column names

• Each column heading will take its value from an element in the array of column names

Page 133: Chapter 3 Adapter Summary prepared by Kirk Scott 1

133

Why Object Adaptation, for the Last Time

• The fact that the adapter adapts an array of rockets dictates the use of an object adapter

• The adapter class could not logically be a “subclass of an array of rockets” as it would have to be if it were a class adapter

• It is an object adapter that adapts to a collection of data objects

• This is necessary because what you’re adapting to, a table, has multiple entries

Page 134: Chapter 3 Adapter Summary prepared by Kirk Scott 1

134

The Desired Result

• The purpose of all the machinery is to be able to display rocket information in a table

• The screenshot illustrating this result is shown again on the following overhead

Page 135: Chapter 3 Adapter Summary prepared by Kirk Scott 1

135

Page 136: Chapter 3 Adapter Summary prepared by Kirk Scott 1

136

Partial Code for the RocketTableModel Class

• As usual, the code for the solution to the problem is given as a challenge

• Instead, the complete code is given on the following overheads

Page 137: Chapter 3 Adapter Summary prepared by Kirk Scott 1

137

• import javax.swing.table.*;• import com.oozinoz.firework.Rocket;

• public class RocketTableModel extends AbstractTableModel {

• protected Rocket[] rockets;• protected String[] columnNames = new String[]

{ "Name", "Price", "Apogee" };

• public RocketTableModel(Rocket[] rockets)• {• this.rockets = rockets;• }

Page 138: Chapter 3 Adapter Summary prepared by Kirk Scott 1

138

• public int getColumnCount()• {• return columnNames.length;• }

• public String getColumnName(int i)• {• return columnNames[i];• }

• public int getRowCount()• {• return rockets.length;• }

Page 139: Chapter 3 Adapter Summary prepared by Kirk Scott 1

139

• public Object getValueAt(int row, int col)• {• switch (col)• {• case 0:• return rockets[row].getName();• case 1:• return rockets[row].getPrice();• case 2:• return new Double(rockets[row].getApogee());• default:• return null;• }• }

Page 140: Chapter 3 Adapter Summary prepared by Kirk Scott 1

140

An Example of Using the RocketTableModel Adapter

• The book provides example application code which uses the RocketTableModel adapter

• In this code, instances of Rocket are created and placed in an array

• An instance of RocketTableModel is constructed with the rocket array passed in as a parameter

• Swing classes are used to display the table• Code for this example application follows

Page 141: Chapter 3 Adapter Summary prepared by Kirk Scott 1

141

• import java.awt.Component;• import java.awt.Font;• import javax.swing.*;• import com.oozinoz.firework.Rocket;• import com.oozinoz.utility.Dollars;

• public class ShowRocketTable• { • public static void main(String[] args)• {• setFonts();

• JTable table = new JTable(getRocketTable());• table.setRowHeight(36);• JScrollPane pane = new JScrollPane(table);• pane.setPreferredSize(new java.awt.Dimension(300, 100));• display(pane, " Rockets");• }•

Page 142: Chapter 3 Adapter Summary prepared by Kirk Scott 1

142

• public static void display(Component c, String title)• {• JFrame frame = new JFrame(title);• frame.getContentPane().add(c);• frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • frame.pack();• frame.setVisible(true);• }

• private static RocketTableModel getRocketTable()• {• Rocket r1 = new Rocket("Shooter", 1.0, new Dollars(3.95), 50.0, 4.5);• Rocket r2 = new Rocket("Orbit", 2.0, new Dollars(29.03), 5000, 3.2);• return new RocketTableModel(new Rocket[] { r1, r2 });• }

• private static void setFonts()• {• Font font = new Font("Dialog", Font.PLAIN, 18);• UIManager.put("Table.font", font);• UIManager.put("TableHeader.font", font);• }

Page 143: Chapter 3 Adapter Summary prepared by Kirk Scott 1

143

Summarizing the Example

• The book sums up this example in this way:• The ShowRocketTable class is a short

application that can show rocket information in an instance of JTable

• It can be short and sweet because of the existence of the TableModel interface, the AbstractTableModel class, and the RocketTableModel class which extends the abstract class

Page 144: Chapter 3 Adapter Summary prepared by Kirk Scott 1

144

• The RocketTableModel implements the object adapter design pattern

• It has instances of the Rocket class in it• It is information about these instances of the

Rocket class that is used to fill the rows of the JTable generated by the ShowRocketTable application

Page 145: Chapter 3 Adapter Summary prepared by Kirk Scott 1

145

Why JTable and the Pattern?

• When the JTable is created, an instance of the concrete model class is passed to it

• The JTable class can’t know in advance which of the many types of data an application may wish to display in its cells

Page 146: Chapter 3 Adapter Summary prepared by Kirk Scott 1

146

• The model contains the needed information, and the JTable code can obtain it from the model

• All we have to do is implement the needed methods in the concrete model because calls internal to the JTable rely on those methods

Page 147: Chapter 3 Adapter Summary prepared by Kirk Scott 1

147

• The Java API makes use of the object adapter design pattern in order to make it easy to display object data in a table

• The example code could easily be rewritten to make an adapter for any kind of object that you’d like to display in a table

• The burden of creating the table itself is removed from the programmer

Page 148: Chapter 3 Adapter Summary prepared by Kirk Scott 1

148

A UML Diagram for the Pattern from Lasater

• Lasater’s UML diagram is given on the next overhead.

• Which of the two adapter patterns is shown?

Page 149: Chapter 3 Adapter Summary prepared by Kirk Scott 1

149

Page 150: Chapter 3 Adapter Summary prepared by Kirk Scott 1

150

Summary

• A class adapter implements an interface and extends a class in order to adapt the class to the interface

• An object adapter extends a class and makes use of objects in order to adapt the objects to the class

• The Java API makes use of adaptation in order to create tables of data

Page 151: Chapter 3 Adapter Summary prepared by Kirk Scott 1

151

The End