Adapter https://msdn.microsoft.com/en-us/library/orm-9780596527730-01-04.aspx.

Slides:



Advertisements
Similar presentations
Observer Method 1. References Gamma Erich, Helm Richard, “Design Patterns: Elements of Reusable Object- Oriented Software” 2.
Advertisements

Matt Klein. Decorator Pattern  Intent  Attach Additional responsibilities to an object by dynamically. Decorators provide a flexible alternative to.
1 Structural Design Patterns - Neeraj Ray. 2 Structural Patterns - Overview n Adapter n Bridge n Composite n Decorator.
02 - Structural Design Patterns – 1 Moshe Fresko Bar-Ilan University תשס"ח 2008.
CS 211 Inheritance AAA.
Chapter 8 Inheritance Part 2. © 2004 Pearson Addison-Wesley. All rights reserved8-2 Outline Creating Subclasses Overriding Methods Class Hierarchies Inheritance.
The Bridge Pattern.. Intent Decouple an abstraction from its implementation so that the two can vary independently Also known as: Handle/Body.
Object-Oriented PHP (1)
Aalborg Media Lab 23-Jun-15 Inheritance Lecture 10 Chapter 8.
ADAPTER PATTERN Ali Zonoozi Design patterns course Advisor: Dr. Noorhoseini Winter 2010.
Design Patterns Based on Design Patterns. Elements of Reusable Object-Oriented Software. by E.Gamma, R. Helm, R. Johnson,J. Vlissides.
Adapters Presented By Zachary Dea. Definition A pattern found in class diagrams in which you are able to reuse an ‘adaptee’ class by providing a class,
The Composite Pattern.. Composite Pattern Intent –Compose objects into tree structures to represent part-whole hierarchies. –Composite lets clients treat.
ECE450 - Software Engineering II1 ECE450 – Software Engineering II Today: Design Patterns VI Composite, Iterator, and Visitor Patterns.
1 An introduction to design patterns Based on material produced by John Vlissides and Douglas C. Schmidt.
Creational Patterns Making Objects The Smart Way Brent Ramerth Abstract Factory, Builder.
Design Patterns.
1 Dept. of Computer Science & Engineering, York University, Toronto CSE3311 Software Design Adapter Pattern Façade pattern.
ADAPTER PATTERN BY Sravanthi Karumanchi. Structure Pattern Structure patterns are concerned with how classes and objects are composed to form large structures.
CS 325: Software Engineering March 17, 2015 Applying Patterns (Part A) The Façade Pattern The Adapter Pattern Interfaces & Implementations The Strategy.
Department of Computer Science, York University Object Oriented Software Construction 13/10/ :44 AM 0 CSE3311 – Software Design Adapter Pattern.
CSCI-383 Object-Oriented Programming & Design Lecture 13.
18 April 2005CSci 210 Spring Design Patterns 1 CSci 210.
Decorator Explained. Intent Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for.
Structural Design Patterns
ECE450 - Software Engineering II1 ECE450 – Software Engineering II Today: Design Patterns IV Structural Patterns.
ECE450 - Software Engineering II1 ECE450 – Software Engineering II Today: Design Patterns VIII Chain of Responsibility, Strategy, State.
Factory Method Explained. Intent  Define an interface for creating an object, but let subclasses decide which class to instantiate.  Factory Method.
08 - StructuralCSC4071 Structural Patterns concerned with how classes and objects are composed to form larger structures –Adapter interface converter Bridge.
Linzhang Wang Dept. of Computer Sci&Tech, Nanjing University The Strategy Pattern.
Review Class Inheritance, Abstract, Interfaces, Polymorphism, GUI (MVC)
Object-Oriented Programming Chapter Chapter
Object Oriented Programming
1 Advanced Object-oriented Design – Principles and Patterns Structural Design Patterns.
The Decorator Pattern (Structural) ©SoftMoore ConsultingSlide 1.
S.Ducasse Stéphane Ducasse 1 Adapter.
COMPOSITE PATTERN NOTES. The Composite pattern l Intent Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients.
CLASSIFICATION OF DESIGN PATTERNS Hladchuk Maksym.
Inheritance Modern object-oriented (OO) programming languages provide 3 capabilities: encapsulation inheritance polymorphism which can improve the design,
Modern Programming Tools And Techniques-I
OOP - Object Oriented Programming
Design Patterns: MORE Examples
Design Patterns: Brief Examples
Visit for more Learning Resources
Design Patterns Spring 2017.
Structural Patterns Structural patterns control the relationships between large portions of your applications. Structural patterns affect applications.
MPCS – Advanced java Programming
Linzhang Wang Dept. of Computer Sci&Tech, Nanjing University
Factory Patterns 1.
Inheritance and Polymorphism
Behavioral Design Patterns
Java Beans Sagun Dhakhwa.
Distribution and components
Adapter Design Pattern
Decorator Design Pattern
Design Patterns A Case Study: Designing a Document Editor
Jim Fawcett CSE776 – Design Patterns Summer 2003
Lecture 22 Inheritance Richard Gesick.
Software Design Lecture : 9.
Ms Munawar Khatoon IV Year I Sem Computer Science Engineering
An Introduction to Software Architecture
Structural Patterns: Adapter and Bridge
Introduction to Design Patterns
Object-Oriented PHP (1)
Chapter 8 Inheritance Part 2.
Decorator Pattern.
ECE 352 Digital System Fundamentals
Adapter Pattern Jim Fawcett
C++ Object Oriented 1.
Adapter Pattern Jim Fawcett
Presentation transcript:

Adapter https://msdn.microsoft.com/en-us/library/orm-9780596527730-01-04.aspx

Adapter – motivation and concept Component designed to connect two "incompatible" devices In this scenario: A type of plug which makes it possible to connect two or more pieces of equipment (with different power plugs) to the same electrical supply We can think of the adapter in terms of the problem of inserting a new two-prong electrical plug in an old three-prong wall outlet – some kind of adapter or intermediary is necessary. 2 2 2 2

Adapter – design pattern Also called “Wrapper” Structural Design Pattern Building simple hierarchies and relations between different classes Links existing classes with an incompatible interface Without altering them – same underlying behaviour Asymmetric - one class "connects to the other" An adapter lets classes work together that couldn't otherwise because of incompatible interfaces. Sometimes a toolkit class that's designed for reuse isn't reusable only because its interface doesn't match the domain-specific interface an application requires. Clients call operations on an Adapter instance. In turn, the adapter calls Adaptee operations that carry out the request. The intention of using an adapter is to NOT change the underlying behaviour of the components. It serves as an intermediary for communication to occur without altering behaviour. Structural patterns are concerned with how classes and objects are composed to form larger structures. Structural class patterns use inheritance to compose interfaces or implementations. As a simple example, consider how Multiple inheritance mixes two or more classes into one. The result is a class that combines the properties of its parent classes. Rather than composing interfaces or implementations, structural object patterns describe ways to compose objects to realize new functionality. The added flexibility of object composition comes from the ability to change the composition at run-time, which is impossible with static class composition. 3 3 3 3

Adapter – participants Target (defines the interface required by the Client) Client (we adapt for) Adaptee (defines the interface the Client wants to use) Adapter (adapts Adaptee to Target Interface) The client expects the target to be a round 2-pin socket, however what if we want to integrate some library that requires a square 2-pin socket? Then we must use an adapter that satisfies both. As can be seen from the picture, the adapter accepts both round and square 2-pin plugs. Complex adapters accept multiple inputs of different types. Adapter used so the adaptee adapts to Target interface required by the client. 4 4 4 4

Inherited implementation Adapter – two connection options Object Adapter Class Adapter Composition “has a“ Client Target Request() Adapter Adaptee->SpecificRequest() Adaptee SpecificRequest() Public inheritance “is a“ Private inheritance “is implemented in terms of“ Client Target Request() Adapter SpecificRequest() Adaptee Public inheritance “is a“ Inherited implementation Clients call operations on an Adapter instance. In turn, the adapter calls Adaptee operations that carry out the request. 5 5 5

Adapter – Drawing App example Consider for example a drawing editor that lets users draw and arrange graphical elements (lines, polygons, text, etc.) into pictures and diagrams. The drawing editor's key abstraction is the graphical object, which has an editable shape and can draw itself. The interface for graphical objects is defined by an abstract class called Shape. The editor defines a subclass of Shape for each kind of graphical object: a LineShape class for lines, a PolygonShape class for polygons, and so forth. Classes for elementary geometric shapes like LineShape and PolygonShape are rather easy to implement, because their drawing and editing capabilities are inherently limited. But a TextShape subclass that can display and edit text is considerably more difficult to implement, since even basic text editing involves complicated screen update and buffer management. Meanwhile, an off-the-shelf user interface toolkit might already provide a sophisticated TextView class for displaying and editing text. Ideally we'd like to reuse TextView to implement TextShape, but the toolkit wasn't designed with Shape classes in mind. So we can't use TextView and Shape objects interchangeably. How can existing and unrelated classes like TextView work in an application that expects classes with a different, incompatible interface? We could change the TextView class so that it conforms to the Shape interface, but that isn't an option unless we have the toolkit's source code. Even if we did, it wouldn't make sense to change TextView; the toolkit shouldn't have to adopt domain-specific interfaces just to make one application work. Instead, we could define TextShape so that it adapts the TextView interface to Shape's. We can do this in one of two ways: (1) by inheriting Shape's interface and TextView's implementation or (2) by composing a TextView instance within a TextShape and implementing TextShape in terms of TextView's interface. These two approaches correspond to the class and object versions of the Adapter pattern. We call TextShape an adapter. 6 6 6 6

Adapter – example Target Shape defines the target interface class Shape { virtual void BoundingBox( Point& bottomLeft, Point& topRight ) const; virtual Manipulator* CreateManipulator() const; }; Adaptee TextView implements some methods, but in another interface As can be seen above, the interfaces for Shape and TextView are completely different and requite an adapter. Shape assumes a bounding box defined by its opposing corners. In contrast, TextView is defined by an origin, height, and width. Shape also defines a CreateManipulator operation for creating a Manipulator object, which knows how to animate a shape when the user manipulates it.1 TextView has no equivalent operation. The class TextShape is an adapter between these different interfaces. class TextView { void GetOrigin( Coord& x, Coord& y ); void GetExtent( Coord& width, Coord& height ); virtual bool IsEmpty() const; }; 7 7 7 7

Object Adapter 8 8 8 8

Object Adapter – example Client works with Shape descendants Target defines the target interface Adaptee has its own interface Composition „has a“ DrawingApp Shape BoundingBox() TextShape _text->GetExtent() TextView GetExtent() Public inheritance „is a“ An object adapter relies on object composition. An instance of TextView is created in the TextShape class and its GetExtent method is invoked inside the BoundingBox method, possibly followed by more logic to adapt the results to the format required by the Shape interface. Adapter adapts TextView to the Shape interface 9 9 9 9

Object Adapter TextShape publicly inherits from Object Adapter – example Object Adapter TextShape Object Adapter TextShape publicly inherits from Target Shape class TextShape: public Shape { public: TextShape(TextView* t); virtual void BoundingBox(Point& bottomLeft, Point& topRight) const; virtual bool IsEmpty() const; virtual Manipulator* CreateManipulator(); private: TextView* _text; }; As can be seen from the above sample code, the TextShape class contains an instantiation/declaration of the TextView class, so once it is assigned, its methods can be invoked in the TextShape implementation. The object adapter uses object composition to combine classes with different interfaces. In this approach, the adapter TextShape maintains a pointer to TextView. Often the adapter is responsible for functionality the adapted class doesn't provide. The diagram shows how an adapter can fulfill such responsibilities. The user should be able to "drag" every Shape object to a new location interactively, but TextView isn't designed to do that. TextShape can add this missing functionality by implementing Shape's CreateManipulator operation, which returns an instance of the appropriate Manipulator subclass. Adaptee TextView is a private member of TextShape Adapter 10 10 10

Object Adapter – example Object Adapter TextShape – implementation TextShape::TextShape(TextView* t) { _text = t; } void TextShape::BoundingBox(Point& bottomLeft, Point& topRight) const Coord bottom, left, width, height; _text -> GetOrigin( bottom, left ); _text -> GetExtent( width, height ); topRight = Point( bottom + height, left + width ); bottomLeft = Point( bottom, left ); bool TextShape::IsEmpty() const return _text->IsEmpty(); Manipulator* TextShape::CreateManipulator() const return new TextManipulator(this); the constructor requires an existing Adaptee instance TextShape must initialize the pointer to the TextView instance, and it does so in the constructor. It must also call operations on its TextView object whenever its own operations are called. In this example, assume that the client creates the TextView object and passes it to the TextShape constructor. The methods in the TextView adaptee instance can then be invoked by calling the methods on that instance. For example, the GetOrigin method is invoked, which updates the parameters passed by reference. The same can be said for the GetExtent method. The values computed by the adaptee’s method can then be used to update the Point objects passed by reference. The IsEmpty method also invokes a method of the adaptee instance, however this one simply returns its result since it returns a bool as does the TextShape method. Manipulator is an abstract class for objects that know how to animate a Shape in response to user input, like dragging the shape to a new location. There are subclasses of Manipulator for different shapes; TextManipulator, for example, is the corresponding subclass for TextShape. By returning a TextManipulator instance, TextShape adds the functionality that TextView lacks but Shape requires. invoke Adaptee method and simply return its result 11 11 11

Object Adapter – properties Uses composition Adaptee is a private data item of Adapter May arise as a wrapper around an existing instance of Adaptee Example – TextShape::TextShape(TextView* t) Can adapt all descendants of Adaptee Example – any descendant of TextView Does not have access to the protected items of the Adaptee itself Cannot redefine Adaptee items Indirect - subclass Adaptee, redefined and used in Adapter instead of Adaptee Use the Adapter pattern when: · you want to use an existing class, and its interface does not match the one you need. · you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces. · (object adapter only) you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class. We say it may arise as a wrapper because the adapter’s methods can invoke methods of the adaptee and then modify the results to the expected output. Thus, a method doesn’t necessarily solely call an adaptee’s method. An object adapter lets a single Adapter work with many Adaptees—that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once. A downfall is that it makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself. 12 12 12

Class Adapter In general, an adapter makes one interface (the adaptee's) conform to another, thereby providing a uniform abstraction of different interfaces. A class adapter accomplishes this by inheriting privately from an adaptee class. The adapter then expresses its interface in terms of the adaptee's. 13 13 13 13

Inherited implementation Class Adapter – example Private inheritance „is implemented in terms of“ DrawingApp Shape BoundingBox() TextShape GetExtent() TextView Public inheritance „is a“ Inherited implementation Adapter inherits both Target and Adaptee A class adapter uses multiple inheritance to adapt one interface to another. Adapter can directly call the Adaptee method when implementing Target 14 14 14 14

Class Adapter – example Class Adapter TextShape Multiple Inheritance public from Target private from Adaptee class TextShape: public Shape, private TextView { public: TextShape(); virtual void BoundingBox( Point& bottomLeft, Point& topRight ) const; virtual bool IsEmpty() const; virtual Manipulator* CreateManipulator() }; A class adapter uses multiple inheritance to adapt interfaces. The key to class adapters is to use one inheritance branch to inherit the interface and another branch to inherit the implementation. The usual way to make this distinction in C++ is to inherit the interface publicly and inherit the implementation privately. We'll use this convention to define the TextShape adapter. 15 15 15 15

Class Adapter – example Class Adapter TextShape – implementation metod void BoundingBox( Point& bottomLeft, Point& topRight ) const { Coord bottom, left, width, height; GetOrigin( bottom, left ); GetExtent( width, height ); topRight = Point( bottom + height, left + width ); bottomLeft = Point( bottom, left ); } bool TextShape::IsEmpty() const return TextView::IsEmpty(); Manipulator* TextShape::CreateManipulator() const return new TextManipulator( this ); Direct calling methods of the ancestor Direct calling methods of the ancestor Direct calling methods of the ancestor The BoundingBox operation converts TextView's interface to conform to Shape's. The IsEmpty operation demonstrates the direct forwarding of requests common in adapter implementations. Finally, we define CreateManipulator (which isn't supported by TextView) from scratch. Assume we've already implemented a TextManipulator class that supports manipulation of a TextShape. CreateManipulator's implementation doesn't change from the object adapter version, since it's implemented from scratch and doesn't reuse any existing TextView functionality. 16 16 16 16

Class Adapter – properties There is no indirection when delegating methods Methods are called directly, not using pointers Uses multiple inheritance Access to protected Adaptee items can be redefined Can override some Adaptee behaviour Multiple (class) inheritance is not supported by many languages But we can inherit from multiple interfaces Cannot adapt subclasses of Adaptee Class and object adapters have different trade-offs. A class adapter · adapts Adaptee to Target by committing to a concrete Adapter class. As a consequence, a class adapter won't work when we want to adapt a class and all its subclasses. · lets Adapter override some of Adaptee's behavior, since Adapter is a subclass of Adaptee. · introduces only one object, and no additional pointer indirection is needed to get to the adaptee. Compare this code to the object adapter case. The object adapter requires a little more effort to write, but it's more flexible. For example, the object adapter version of TextShape will work equally well with subclasses of TextView—the client simply passes an instance of a TextView subclass to the TextShape constructor. 17 17 17

Implementation notes How much work needs to be done by the Adapter itself? Simple conversion between differently named methods Operation not supported by Adaptee - Processing logic Sometimes it implements the Adapter without the help of Adaptee Adapter does not necessarily have to adapt only one class bool TextShape::IsEmpty() const { return TextView::IsEmpty(); } Manipulator* TextShape::CreateManipulator() const { return new TextManipulator(this); } Here are other issues to consider when using the Adapter pattern: 1. How much adapting does Adapter do? Adapters vary in the amount of work they do to adapt Adaptee to the Target interface. There is a spectrum of possible work, from simple interface conversion—for example, changing the names of operations—to supporting an entirely different set of operations. The amount of work Adapter does depends on how similar the Target interface is to Adaptee's. 2. Pluggable adapters. A class is more reusable when you minimize the assumptions other classes must make to use it. By building interface adaptation into a class, you eliminate the assumption that other classes see the same interface. Put another way, interface adaptation lets us incorporate our class into existing systems that might expect different. The first step, which is common to all three of the implementations discussed here, is to find a "narrow" interface for Adaptee, that is, the smallest subset of operations that lets us do the adaptation. A narrow interface consisting of only a couple of operations is easier to adapt than an interface with dozens of operations. For TreeDisplay, the adaptee is any hierarchical structure. A minimalist interface might include two operations, one that defines how to present a node in the hierarchical structure graphically, and another that retrieves the node's children. 18 18 18

Some other variations of implementation Two-way Adapter Interchangeability of the Adapter behind Adaptee objects It behaves like Target and Adaptee Typical implementation with multiple public inheritance Pluggable Adapter Up to now - one Client, one Adaptee Many Adapters for Many Adjusted Classes An adapter that isn't hard-coded against a specific Adaptee Can adapt to different Adaptees with different interfaces Unified interface for adapting all representations Minimal – “narrow interface“ Implementation types: Abstract methods Delegate Two-way adapter combines functionality from both the target and adaptee. DigitalAnalogData is a subclass of both DigitalData and AnalogData, that adapts the two interfaces to each other. Multiple inheritance is a viable solution in this case because the interfaces of the adapted classes are substantially different. The two-way class adapter conforms to both of the adapted classes and can work in either system. Adapters provide access to some behavior in the Adaptee (the behavior required in the ITarget interface), but Adapter objects are not interchangeable with Adaptee objects. They cannot be used where Adaptee objects can because they work on the implementation of the Adaptee, not its interface. Sometimes we need to have objects that can be transparently ITarget or Adaptee objects. This could be easily achieved if the Adapter inherited both from both classes; however, such multiple inheritance is not possible in C#, so we must look at other solutions. The two-way adapter addresses the problem of two systems where the characteristics of one system have to be used in the other, and vice versa. An Adapter class is set up to absorb the important common methods of both and to provide adaptations to both. The resulting adapter objects will be acceptable to both sides. Theoretically, this idea can be extended to more than two systems, so we can have multiway adapters, but there are some implementation limitations: without multiple inheritance, we have to insert an interface between each original class and the adapter. Pluggable adapter - adapter should support the adaptees (which are unrelated and have different interfaces) using the same old target interface known to the client. A pluggable adapter is an adapter that isn't hard-coded against a specific adaptee. On the surface (the adapter's own interface), it's all the same but it can adapt to different adaptees with different interfaces. Basically, it allows you to put in an adapter when the adaptee (receiver) protocol is not known at compile time by using reflection. When you create the adapter instance, you pass it the name of the adaptee's method to call, and also any metadata that's necessary to translate input types. When the adapter receives a method call of the target interface, it uses reflection to call the corresponding method specified on the adaptee. Developers who recognize that their systems will need to work with other components can increase their chances of adaptation. Identifying in advance the parts of the system that might change makes it easier to plug in adapters for a variety of new situations. Keeping down the size of an interface also increases the opportunities for new systems to be plugged in. Although not technically different from ordinary adapters, this feature of small interfaces gives them the name pluggable adapters. A distinguishing feature of pluggable adapters is that the name of a method called by the client and that existing in the ITarget interface can be different. The adapter must be able to handle the name change. In the previous adapter variations, this was true for all Adaptee methods, but the client had to use the names in the ITarget interface. Suppose the client wants to use its own names, or that there is more than one client and they have different terminologies. To achieve these name changes in a very dynamic way, we can use delegates. 19 19 19

Pluggable Adapter – Abstract methods Narrow interface part TreeDisplay – abstract methods Default implementation of tree view The narrow interface leads to three implementation approaches: a. Using abstract operations. Define corresponding abstract operations for the narrow Adaptee interface in the TreeDisplay class. Subclasses must implement the abstract operations and adapt the hierarchically structured object. For example, a DirectoryTreeDisplay subclass will implement these operations by accessing the directory structure. DirectoryTreeDisplay specializes the narrow interface so that it can display directory structures made up of FileSystemEntity objects. Descendants implement a narrow interface 20 20 20 20

Pluggable Adapter – Delegate Narrow interface in a separate class/interface Delegate Composition b. Using delegate objects. In this approach, TreeDisplay forwards requests for accessing the hierarchical structure to a delegate object. TreeDisplay can use a different adaptation strategy by substituting a different delegate. For example, suppose there exists a DirectoryBrowser that uses a TreeDisplay. DirectoryBrowser might make a good delegate for adapting TreeDisplay to the hierarchical directory structure. In dynamically typed languages like Smalltalk or Objective C, this approach only requires an interface for registering the delegate with the adapter. Then TreeDisplay simply forwards the requests to the delegate. NEXTSTEP [Add94] uses this approach heavily to reduce subclassing. Statically typed languages like C++ require an explicit interface definition for the delegate. We can specify such an interface by putting the narrow interface that TreeDisplay requires into an abstract TreeAccessorDelegate class. Then we can mix this interface into the delegate of our choice—DirectoryBrowser in this case—using inheritance. We use single inheritance if the DirectoryBrowser has no existing parent class, multiple inheritance if it does. Mixing classes together like this is easier than introducing a new TreeDisplay subclass and implementing its operations individually. Descendants implement a narrow interface Access to a narrow interface via a delegate 21 21 21 21

encapsulate some method Pluggable Adapter – Delegate (C# example) class Cat //Adaptee 1   {public static void Meow() { Console.WriteLine(“Meow!"); }} class Dog //Adaptee 2  {public static void Bark() { Console.WriteLine(“Woof!"); }} class Adapter  {     public Action MakeSound { get; private set;} // "pluggable" adapter     public Adapter(Action makeSoundAction)      {         MakeSound = makeSoundAction;     } } class SoundMaker //Client {     static void Main(string[] args)     {         (new Adapter(Cat.Meow)).MakeSound();         (new Adapter(Dog.Bark)).MakeSound();     } } Action Delegate encapsulate some method The adapter class can accept adaptees of different types and perform its job on them regardless of the fact they do different things. The methods of the different adaptees are treated as variables. Action encapsulates a method that has no parameters and does not return a value. It returns a delegate to that method. 22 22 22

Pluggable Adapter – properties Abstract methods Client is also Target, inheriting directly from it The Adaptee interface is only suitable for the object-adapter Target is not just an interface - multiple inheritance required Delegate Delegating a narrow interface to a delegated class Access methods through a pointer A pointer back to the Client Possible object and class adapter Two objects – Client and Adapter c. Parameterized adapters. The usual way to support pluggable adapters in Smalltalk is to parameterize an adapter with one or more blocks. The block construct supports adaptation without subclassing. A block can adapt a request, and the adapter can store a block for each individual request. In our example, this means TreeDisplay stores one block for converting a node into a GraphicNode and another block for accessing a node's children. 23 23 23

Adapter – usage When to use Known uses Use an existing class with an incompatible interface Creating a reusable class that uses classes with a potentially incompatible interface Known uses C# – ADO.NET DataAdapter – data queries independent of the data source Usage in DataSet Java I/O StringBufferInputStream – adapts StringBuffer as InputStream Pluggable Adapter in Swing javax.swing.tree.TreeModel – JTree component viewing interface Smalltalk introduced the concept of a "pluggable adapter" to describe classes with built-in interface adaptation. This interesting concept allows for classes to be introduced into existing systems that might expect different interfaces to the class. This technique can help promote class reuse across modules and even projects. 24 24 24 24

Adapter – related design patterns Related DPs Bridge Decouple interface from implementation Does not change the interface Used at design time Decorator Does not change the interface of the object Adds functionality Support recursive composition Proxy Hides the actual location of the object (e.g. object on disk, on another computer) Facade Provides a simplified interface Hides the complexities of a larger system 25 25 25 25