Clever Geek Handbook
πŸ“œ ⬆️ ⬇️

Adapter (design pattern)

Adapter ( English Adapter ) is a structural design pattern intended for organizing the use of functions of an object that is not available for modification through a specially designed interface . In other words, it is a structural design pattern that allows objects with incompatible interfaces to work together.

Adapter
Adapter
Adapter pattern.svg
Adapter Template Structure Representation
Type ofstructural
Purposeto organize the use of functions of an object that is unavailable for modification through a specially created interface (leads an interface of a class (or several classes) to an interface of the required type)
Used in casesThe system supports the required data and behavior, but has an inappropriate interface. Most often, the Adapter pattern is used if it is necessary to create a class derived from a newly defined or already existing abstract class.
pros
  • encapsulating the implementation of external classes (components, libraries), the system becomes independent of the interface of external classes;
  • transition to the use of other external classes does not require alteration of the system itself, it is enough to implement one Adapter class.
Related TemplatesFacade Decorator
Described in Design PatternsYes

Content

Key Features

Task

The system supports the required data and behavior, but has an inappropriate interface.

Solution Method

The adapter provides for the creation of a wrapper class [1] with the required interface.

Members

The Adapter class brings the interface of the Adaptee class to the interface of the Target class (which is implemented by the Adapter class). This allows the Client object to use the Adaptee (via the Adapter adapter) as if it were an instance of the Target class.

Thus, Client accesses the Target interface implemented by the Adapter class, which redirects the call to Adaptee .

 

Consequences

The Adapter pattern allows you to include already existing objects in new object structures, regardless of differences in their interfaces.

Comments and Comments

The Adapter pattern allows the design process not to take into account possible differences in the interfaces of existing classes. If there is a class with the required methods and properties (at least conceptually), then, if necessary, you can always use the Adapter template to bring its interface to the desired form.

Close to the Adapter is the Facade pattern, it is not always possible to distinguish one from the other [2] .

Applying a pattern

A typical example of using the Adapter pattern is the creation of classes leading to a single interface of the PHP language function providing access to various DBMS [3] .

A solution to this problem using the Adapter pattern is shown in the figure.

 
An example of using the Adapter pattern

Implementation

Inclusion of an existing class in another class. The interface of the enclosing class is brought in line with the new requirements, and calls to its methods are converted to calls to the methods of the included class.


Implementation Steps

  1. Make sure you have two classes with incompatible interfaces:
    • A useful service is a utility class that you cannot change (it is either third-party or another code depends on it);
    • One or several clients - existing application classes that are incompatible with the service due to an inconvenient or mismatched interface.
  2. Describe the client interface through which application classes could use the service class.
  3. Create an adapter class by implementing this interface.
  4. Place in the adapter the field that will store the link to the service object. Usually this field is filled with the object passed to the adapter constructor. In the case of simple adaptation, this object can be passed through the parameters of the adapter methods.
  5. Implement all client interface methods in the adapter. The adapter must delegate the main work to the service.
  6. The application should use the adapter only through the client interface. This will make it easy to change and add adapters in the future.


Ruby

Ruby Example
  module AdapterPattern
   # Allows Client to use Adaptees with incompatible interfaces via Adapters with interface Target

   # Adaptee
   class twitter
     def twit
       puts 'Twit was published'
     end
   end

   # Adaptee
   class Facebook
     def post
       puts 'Facebook post was published'
     end
   end

   # Target
   module WebServiceInterface
     def send_message
       raise NotImplementedError
     end
   end

   # Adapter
   class TwitterAdapter
     include WebServiceInterface

     def initialize
       @webservice = Twitter .  new
     end

     def send_message
       @webservice .  twit
     end
   end

   # Adapter
   class FacebookAdapter
     include WebServiceInterface

     def initialize
       @webservice = Facebook .  new
     end

     def send_message
       @webservice .  post
     end
   end

   # Client
   class Message
     attr_accessor : webservice

     def send
       @webservice .  send_message
     end
   end

   def self .  run
     puts '=> Adapter'

     message = Message .  new

     message .  webservice = TwitterAdapter .  new
     message .  send

     message .  webservice = FacebookAdapter .  new
     message .  send

     puts ''
   end
 end

 AdapterPattern .  run

Java inheritance

Java example (through inheritance)
  // Target
 public interface Chief
 {
   public Object makeBreakfast ();
   public Object makeLunch ();
   public Object makeDinner ();
 }

 // Adaptee
 public class Plumber
 {
   public Object getScrewNut ()
   { ... }
   public Object getPipe ()
   { ... }
   public Object getGasket ()
   { ... }
 }

 // Adapter
 public class ChiefAdapter extends Plumber implements Chief
 {
   public Object makeBreakfast ()
   {
     return getGasket ();
   }
   public Object makeLunch ()
   {
     return getPipe ();
   }
   public Object makeDinner ()
   {
     return getScrewNut ();
   }
 }

 // Client
 public class Client
 {
   public static void eat ( Object dish )
   { ... }

   public static void main ( String [] args )
   {
     Chief ch = new ChiefAdapter ();
     Object dish = ch .  makeBreakfast ();
     eat ( dish );
     dish = ch .  makeLunch ();
     eat ( dish );
     dish = ch .  makeDinner ();
     eat ( dish );
     callAmbulance ();
   }
 }

Java - composition

Java example (through composition)
  // File Chief.java

 public interface Chief {

	 public Object makeBreakfast ();
	 public Object makeDinner ();
	 public Object makeSupper ();
	
 }

 // File Plumber.java

 public class Plumber {

	 public Object getPipe () {
		 return new Object ();
	 }
	
	 public Object getKey () {
		 return new Object ();
	 }
	
	 public Object getScrewDriver () {
		 return new Object ();
	 }
	
 }

 // File ChiefAdapter.java

 public class ChiefAdapter implements Chief {

	 private Plumber plumber = new Plumber ();

	 @Override
	 public Object makeBreakfast () {
		 return plumber .  getKey ();
	 }

	 @Override
	 public Object makeDinner () {
		 return plumber .  getScrewDriver ();
	 }

	 @Override
	 public Object makeSupper () {
		 return plumber .  getPipe ();
	 }

 }

 // Client.java file

 public class Client {

	 public static void main ( String [] args ) {
		 Chief chief = new ChiefAdapter ();
		
		 Object key = chief .  makeDinner ();
	 }
	
 }

Scala

Scala example
  package object adapter {

   object battlefield {

     protected var redTroops : Array [ Troop ] = Array ()

     protected var blueTroops : Array [ Troop ] = Array ()

     def addTroop ( troop : Troop ) : Unit = {
       if ( troop . side == "red" ) {
         redTroops : + = troop
       } else if ( troop . side == "blue" ) {
         blueTroops : + = troop
       } else {
         throw new Exception ( s "Invalid side $ { troop . side } for troop $ { troop . name } " )
       }
     }

     def getClosestEnemyTroop ( side : String ) : Troop = {
       if ( side == "red" ) {
         getTroop ( blueTroops )
       } else {
         getTroop ( redTroops )
       }
     }

     private def getTroop ( troops : Array [ Troop ]) : Troop = {
       if ( troops . length == 0 ) {
         throw new Exception ( "No available troops" )
       }
       troops ( 0 )
     }
   }

   class Troop (
                 val side : String ,
                 val name : String ,
                 val closeWeapon : String ,
                 val distanceWeapon : String
               ) {

     def move ( direction : String , distance : Int ) : Unit = {
       println ( s "Troop $ name moves $ direction on $ distance yards" )
     }

     def attack ( enemyTroop : Troop , attackType : String ) : Unit = {
       val weapon = attackType match {
         case "distance" => distanceWeapon
         case "close" => closeWeapon
         case _ => throw new Exception ( s "Invalid attack type $ attackType for troop $ name " )
       }

       println ( s "Troop $ name attacks enemy troop $ { enemyTroop . name } with their $ { weapon } s" )
     }
   }

   trait LanceKnightTroopTrait {

     def moveForward ( distance : Int ) : Unit

     def attackClosest ( attackType : String ) : Unit
   }

   class LanceKnightTroop (
                           override val side : String ,
                           override val name : String ,
                           override val closeWeapon : String ,
                           override val distanceWeapon : String
                         )
     extends Troop ( side , name , closeWeapon , distanceWeapon )
     with LanceKnightTroopTrait {

     override def moveForward ( distance : Int ) : Unit = {
       move ( "forward" , distance )
     }

     override def attackClosest ( attackType : String ) : Unit = {
       attack ( Battlefield . getClosestEnemyTroop ( side ), attackType )
     }
   }

   object adapter adapter extends abstracttest {

     override def run () : Unit = {
       val troop = new Troop ( "blue" , "Archers" , "sword" , "longbow" )
       val lanceKnightTroop = new LanceKnightTroop ( "red" , "Lance Knights" , "pike" , "crossbow" )

       Battlefield .  addTroop ( troop )
       Battlefield .  addTroop ( lanceKnightTroop )
       println ( "Output:" )
       lanceKnightTroop .  moveForward ( 300 )
       lanceKnightTroop .  attackClosest ( "close" )
     }
   }
 }

 // Output:
 // Troop Lance Knights moves forward on 300 yards
 // Troop Lance Knights attacks enemy troopers Archers with their pikes

PHP5

PHP 5 Example
  <? php
 class IndependentDeveloper1
 {
     public function calc ( $ a , $ b ) {
         return $ a + $ b ;
     }
 }

 class IndependentDeveloper2
 {
     public function nameIsVeryLongAndUncomfortable ( $ a , $ b ) {
         return $ a + $ b ;
     }
 }

 interface IAdapter
 {
     public function sum ( $ a , $ b );
 }

 class ConcreteAdapter1 implements IAdapter
 {
     protected $ object ;

     public function __construct () {
         $ this -> object = new IndependentDeveloper1 ();
     }
     public function sum ( $ a , $ b ) {
         return $ this -> object -> calc ( $ a , $ b );
     }
 }

 class ConcreteAdapter2 implements IAdapter
 {
     protected $ object ;

     public function __construct () {
         $ this -> object = new IndependentDeveloper2 ();
     }
     public function sum ( $ a , $ b ) {
         return $ this -> object -> nameIsVeryLongAndUncomfortable ( $ a , $ b );
     }
 }
 // in one place we create a specific adapter and then use the interface
 $ adapter1 = new ConcreteAdapter1 ();
 $ adapter2 = new ConcreteAdapter2 ();

 / **
 * Everywhere in the code we do not use classes directly but through the interface
 * this function does not matter which class we use, since we rely on the interface
 *
 * @param IAdapter $ adapter
 * /
 function sum ( IAdapter $ adapter ) {
     echo $ adapter -> sum ( 2 , 2 );
 }

 sum ( $ adapter1 );
 sum ( $ adapter2 );

PHP5.4

PHP 5.4 Example (Trait)
  <? php
 class SomeClass
 {
     public function someSum ( $ a , $ b )
     {
         return $ a + $ b ;
     }
 }

 class AnotherClass
 {
     public function anotherSum ( $ a , $ b )
     {
         return $ a + $ b ;
     }
 }

 trait TAdaptee
 {
     public function sum ( int $ a , int $ b )
     {
         $ method = $ this -> method ;
         return $ this -> $ method ( $ a , $ b );
     }
 }

 class SomeAdaptee extends SomeClass
 {
     use TAdaptee ;
     private $ method = 'someSum' ;
 }

 class AnotherAdaptee extends AnotherClass
 {
     use TAdaptee ;
     private $ method = 'anotherSum' ;
 }

 $ some = new SomeAdaptee ;
 $ another = new AnotherAdaptee ;
 $ some -> sum ( 2 , 2 );
 $ another -> sum ( 5 , 2 );

PHP5.4 Compact

PHP 5.4 Example (Compact)
  <? php

 trait TAdaptee
 {
     public function sum ( int $ a , int $ b )
     {
         $ method = $ this -> method ;
         return $ this -> $ method ( $ a , $ b );
     }
 }

 class SomeClass
 {
     use TAdaptee ;
     private $ method = 'someSum' ;
     public function someSum ( $ a , $ b )
     {
         return $ a + $ b ;
     }
 }

 class AnotherClass
 {
     use TAdaptee ;
     private $ method = 'anotherSum' ;
     public function anotherSum ( $ a , $ b )
     {
         return $ a + $ b ;
     }
 }

 $ some = new SomeClass ;
 $ another = new AnotherClass ;
 $ some -> sum ( 2 , 2 );
 $ another -> sum ( 5 , 2 );

Javascript

JavaScript example
  function Search ( text , word ) {
	 var text = text ;
	 var word = word ;
	 this .  searchWordInText = function () {
		 return text ;
	 };
	 this .  getWord = function () {
		 return word ;
	 };
 };
 function SearchAdapter ( adaptee ) {
	 this .  searchWordInText = function () {
		 return 'These words' + adaptee .  getWord ();
			 + 'found in text' + adaptee .  searchWordInText ();
	 };
 };
 var search = new Search ( "text" , "words" );
 var searchAdapter = new SearchAdapter ( search );
 searchAdapter .  searchWordInText ();

Python

Python example
  class GameConsole :
     def create_game_picture ( self ):
         return 'picture from console'

 class Antenna :
     def create_wave_picture ( self ):
         return 'picture from wave'

 class SourceGameConsole ( GameConsole ):
     def get_picture ( self ):
         return self .  create_game_picture ()

 class SourceAntenna ( Antenna ):
     def get_picture ( self ):
         return self .  create_wave_picture ()

 class TV :
     def __init__ ( self , source ):
         self .  source = source
     def show_picture ( self ):
         return self .  source .  get_picture ()

 g = SourceGameConsole ()
 a = SourceAntenna ()
 game_tv = TV ( g )
 cabel_tv = TV ( a )
 print game_tv .  show_picture ()
 print cabel_tv .  show_picture ()

C #

C # example
  using System ;
 
  namespace Adapter
  {
  
   class MainApp
   {
     static void Main ()
     {
       // Create adapter and place a request
       Target target = new Adapter ();
       target .  Request ();
 
       // Wait for user
       Console .  Read ();
     }
   }
 
   // "Target"
 
   class Target
   {
     public virtual void Request ()
     {
       Console .  WriteLine ( "Called Target Request ()" );
     }
   }
 
   // "Adapter"
 
   class Adapter : Target
   {
     private Adaptee adaptee = new Adaptee ();
 
     public override void Request ()
     {
       // Possibly do some other work
       // and then call SpecificRequest
       adaptee .  SpecificRequest ();
     }
   }
 
   // "Adaptee"
 
   class adaptee
   {
     public void SpecificRequest ()
     {
       Console .  WriteLine ( "Called SpecificRequest ()" );
     }
   }
  }

Delphi

Delphi example
  program Adapter;

 {$ APPTYPE CONSOLE}

 {$ R * .res}

 uses
   System.SysUtils;

 (* Client use interface of class TTarget realized as TAdapter *)
 (* TAdapter redirects *)

 type
   TTarget = class
     function Request: string;  virtual;
   end;

   TAdaptee = class
     function SpecificRequest: string;
   end;

   TAdapter = class (TTarget)
     fAdaptee: TAdaptee;
     function Request: string;  override;
     constructor Create;
   end;

 {TTarget}

 function TTarget.Request: string;
 begin
   Result: = 'Called Target Request ()';
 end;

 {TAdaptee}

 function TAdaptee.SpecificRequest: string;
 begin
   Result: = 'Called SpecificRequest ()';
 end;

 {TAdapter}

 constructor TAdapter.Create;
 begin
   fAdaptee: = TAdaptee.Create;
 end;

 function TAdapter.Request: string;
 begin
 (* Possibly do some other work and when call SpecificRequest *)
   Result: = fAdaptee.SpecificRequest;
 end;

 var target: TTarget;

 begin
   try
     {TODO -oUser -cConsole Main: Insert code here}
     (* create adapter and place a request *)
     target: = TAdapter.Create;
     WriteLn (target.Request);

     WriteLn (# 13 # 10 + 'Press any key to continue ...');
     ReadLn;

     target.Free;
   except
     on E: Exception do
       Writeln (E.ClassName, ':', E.Message);
   end;
 end. 

Notes

  1. ↑ The closeness of the terms shell and wrapper ( English wrapper - is used as a decorator synonym) sometimes leads to confusion and the Adapter is defined as a synonym for the Decorator pattern, while these are two different patterns and the latter solves a different task, namely, connecting additional obligations to to the object.
  2. ↑ The difference is that the Facade pattern is designed to simplify the interface, while the Adapter pattern is designed to bring the various existing interfaces to a single, desired look.
  3. ↑ In older versions of the PHP language, access to the DBMS is implemented as a set of functions, for each DBMS they have different names and, sometimes, a different set of parameters used, which leads to significant problems when switching from one DBMS to another if such a transition is not provided in advance using the Adapter pattern.

Literature

  • Alan Shalloway, James R. Trott. Design patterns. New approach to object-oriented analysis and design = Design Patterns Explained: A New Perspective on Object-Oriented Design. - M .: β€œWilliams” , 2002. - p. 288. - ISBN 0-201-71594-5 .
  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Object-oriented design techniques. Design Patterns = Design Patterns: Elements of Reusable Object-Oriented Software. - SPb: β€œPeter” , 2007. - p. 366. - ISBN 978-5-469-01136-1 . (also ISBN 5-272-00355-1 )
  • Eric Freeman, Elizabeth Freeman. Design Patterns = Head First Design Patterns. - SPb: Peter, 2011. - 656 p. - ISBN 978-5-459-00435-9 .

Links

  • Adapter Pattern (Adapter) - purpose, description, implementation in C ++, advantages and disadvantages
Source - https://ru.wikipedia.org/w/index.php?title=Adapter_ ( design_con_pattern)


More articles:

  • Sony Ericsson Championships 2009
  • Strictly rationed space
  • Dukhovskaya Church (Staraya Russa)
  • Tamga
  • Altai Honey
  • U-456
  • Codiame Motley
  • Haorah - wikipedia
  • SHINee
  • Turkish-Russian practical transcription

All articles

Clever Geek | 2019