1.51k likes | 1.61k Vues
Chapter 3 Adapter. Summary prepared by Kirk Scott. Whimbrel From Wikipedia, the free encyclopedia.
E N D
Chapter 3Adapter Summary prepared by Kirk Scott
WhimbrelFrom Wikipedia, the free encyclopedia • The Whimbrel (Numeniusphaeopus) is a wader in the large family Scolopacidae. It is one of the most widespread of the curlews, breeding across much of subarcticNorth 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.
GodwitFrom Wikipedia, the free encyclopedia • Jump to: navigation, searchFor other uses, see Limosa (disambiguation). • The godwits are a group of large, long-billed, long-legged and strongly migratorywaders of the birdgenusLimosa. 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]
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]
CurlewFrom Wikipedia, the free encyclopedia • Jump to: navigation, searchFor other uses, see Curlew (disambiguation).For other uses of "Numenius", see Numenius. • The curlews/ˈkɜrljuːz/, genusNumenius, 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 scolopacidwaders, together with the godwits which look similar but have straight bills.[1] In Europe "curlew" usually refers to one species, the Eurasian CurlewNumeniusarquata.
Design Patterns in JavaChapter 3Adapter Summary prepared by Kirk Scott
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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;
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; • }
/*** 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); • }
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
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
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
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
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
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
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