Showing posts with label Structural Design Patterns. Show all posts
Showing posts with label Structural Design Patterns. Show all posts

Saturday, 9 November 2013

Adapter Design pattern - Real Time Example [JDBC Driver]

🚀 Enjoying Java Tutorials?

Subscribe to Ram N Java for clean, beginner-friendly core Java tutorials and interview prep!

🔔 Subscribe to Ram N Java

Introduction

The Adapter Design Pattern is a structural design pattern that allows incompatible interfaces to collaborate. One of the best real-world architectural examples of this pattern in the Java ecosystem is the JDBC-ODBC Bridge Driver and the broader JDBC Driver architecture.

The Real-World Problem: Java Applications and Databases

Java applications interact with relational databases using a standard set of interfaces defined in the java.sql package (such as Connection, Statement, and ResultSet). However, native database systems (like Oracle, MySQL, or legacy ODBC databases) have their own proprietary C/C++ libraries, protocols, and APIs that cannot be directly invoked by standard Java code.

Without an adapter layer, every application would need custom logic for each specific vendor database API.

How the JDBC Driver Acts as an Adapter

The JDBC Driver acts as an intermediate adapter bridging the standard Java API and the database-specific native driver:

  • Client: The Java application that executes database queries.
  • Target Interface: Standard JDBC interfaces (java.sql.Driver, Connection, etc.).
  • Adapter: The database-specific JDBC Driver class (e.g., JDBC-ODBC Bridge or MySQL Connector/J).
  • Adaptee: The proprietary database protocol, vendor client library, or native ODBC driver.

When the client invokes a standard method like statement.executeQuery(), the JDBC adapter translates that method call into commands that the underlying database or native API understands.

Adapter Pattern Mapping

Pattern Role JDBC Equivalent
Client Java Application code
Target Interface java.sql.Driver, Connection, Statement
Adapter Database Driver implementation (e.g., JDBC-ODBC Bridge)
Adaptee Native ODBC API or database network protocol

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=H5CzB2SXOHQ

Click the below Image to Enlarge

Adapter Design pattern - Real Time Example [JDBC Driver]

Adapter Design Pattern – Implementation [Mobile Charger]

🚀 Enjoying Java Tutorials?

Subscribe to Ram N Java for clean, beginner-friendly core Java tutorials and interview prep!

🔔 Subscribe to Ram N Java

Introduction

The Adapter Design Pattern is a structural design pattern used to make two incompatible interfaces work seamlessly together. A classic, intuitive real-world analogy is a Mobile Phone Charger: an electrical wall socket provides high voltage (e.g., 120V or 220V), but a mobile phone only requires 9V to charge. Connecting the phone directly to the wall socket is incompatible, so the mobile charger acts as an adapter converting the incoming voltage to what the phone expects.

Adapter Pattern Mapping

Pattern Role Component in Example Description
Client MobilePhone Needs 9V power to charge
Target Interface ITarget Defines get9Volt() method expected by the client
Adaptee ElectricSocket Existing class providing 120V via getVolt()
Adapter MobilePhoneCharger Implements ITarget, fetches 120V, and converts it to 9V

Java Code Implementation

1. The Volt Model Class

public class Volt {
    private int volts;

    public Volt(int volts) {
        this.volts = volts;
    }

    public int getVolts() {
        return volts;
    }

    public void setVolts(int volts) {
        this.volts = volts;
    }
}

2. Adaptee: ElectricSocket

public class ElectricSocket {
    public Volt getVolt() {
        return new Volt(120);
    }
}

3. Target Interface: ITarget

public interface ITarget {
    Volt get9Volt();
}

4. Adapter: MobilePhoneCharger

public class MobilePhoneCharger implements ITarget {
    private ElectricSocket electricSocket = new ElectricSocket();

    @Override
    public Volt get9Volt() {
        Volt v120 = electricSocket.getVolt();
        System.out.println("From Electric Socket, charger got: " + v120.getVolts() + "V");
        
        Volt v9 = convert120VoltTo9Volt(v120);
        System.out.println("Mobile phone charger converted 120V to: " + v9.getVolts() + "V");
        return v9;
    }

    private Volt convert120VoltTo9Volt(Volt v) {
        return new Volt(9);
    }
}

5. Client: MobilePhone

public class MobilePhone {
    public void chargeMe() {
        ITarget target = new MobilePhoneCharger();
        Volt volt = target.get9Volt();
        System.out.println("Mobile phone is charging using: " + volt.getVolts() + "V");
    }

    public static void main(String[] args) {
        MobilePhone mobilePhone = new MobilePhone();
        mobilePhone.chargeMe();
    }
}

Console Output

From Electric Socket, charger got: 120V
Mobile phone charger converted 120V to: 9V
Mobile phone is charging using: 9V

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=G1CozeYNh48

Click the below Image to Enlarge

Adapter Design Pattern – Implementation [Mobile Charger]






















Adapter Design Pattern – Implementation [Mobile Charger] - Class Diagram




























Volt.java

public class Volt
{
private int volts;

public Volt( int v )
{
this.volts = v;
}

public int getVolts()
{
return volts;
}

public void setVolts( int volts )
{
this.volts = volts;
}
}


ElectricSocket.java

public class ElectricSocket
{
public Volt getVolt()
{
return new Volt(120);
}
}


ITarget.java

public interface ITarget
{
public Volt get9Volt();
}


MobilePhoneCharger.java

public class MobilePhoneCharger implements ITarget
{

private ElectricSocket electricSocket = new ElectricSocket();

@Override
public Volt get9Volt()
{
Volt volt = electricSocket.getVolt();
System.out.println("From ElectricSocket MobilePhoneCharger got :" +volt.getVolts() + "v");
Volt convertedVolt=convertVolt(volt,13);
System.out.println("\nMobilePhoneCharger converterd "+volt.getVolts()+"v to "+convertedVolt.getVolts()+"v\n");
return convertedVolt;
}
private Volt convertVolt(Volt v, int i) 
  {
       return new Volt(v.getVolts()/i);
}

}


MobilePhone.java

public class MobilePhone
{

public static void main(String args[])
{
new MobilePhone().chargeMe();
}
public void chargeMe()
{
ITarget target = new MobilePhoneCharger();
Volt volt=target.get9Volt();
System.out.println("Mobile phone is charging using : "+volt.getVolts() + "v");
}
}


Output

From ElectricSocket MobilePhoneCharger got :120v

MobilePhoneCharger converterd 120v to 9v

Mobile phone is charging using : 9v


Thursday, 7 November 2013

Adapter Pattern – Implementation [Class Adapter]

🚀 Enjoying Java Tutorials?

Subscribe to Ram N Java for clean, beginner-friendly core Java tutorials and interview prep!

🔔 Subscribe to Ram N Java

Introduction

The Adapter Design Pattern can be implemented in two ways: Object Adapter (using composition) and Class Adapter (using inheritance). In this tutorial, we focus on the Class Adapter approach using a real-world enterprise integration scenario: connecting an existing Human Resource (HR) System with a Third-Party Billing System.

The Incompatibility Problem

  • Client (HR System): Stores employee data as a two-dimensional String[][] array.
  • Adaptee (Third-Party Billing System): Contains a processSalary() method that only accepts a List<Employee>.

Neither system should be modified. To bridge this gap, we create a Class Adapter that implements the target interface required by the client and inherits (extends) the third-party billing class directly.

Class Adapter Role Mapping

Pattern Role Component in Example Role Description
Client HumanResourceSystem Supplies employee details in String[][] format
Target Interface ITarget Declares processCompanySalary(String[][])
Adaptee ThirdPartyBillingSystem Provides processSalary(List<Employee>)
Class Adapter EmployeeAdapter Extends ThirdPartyBillingSystem and implements ITarget

Step-by-Step Java Implementation

1. The Employee Model Class

public class Employee {
    private int empId;
    private String name;
    private String designation;

    public Employee(int empId, String name, String designation) {
        this.empId = empId;
        this.name = name;
        this.designation = designation;
    }

    public int getEmpId() { return empId; }
    public String getName() { return name; }
    public String getDesignation() { return designation; }
}

2. Adaptee: ThirdPartyBillingSystem

import java.util.List;

public class ThirdPartyBillingSystem {
    public void processSalary(List<Employee> employeeList) {
        for (Employee emp : employeeList) {
            int salary = 0;
            if ("Team Leader".equalsIgnoreCase(emp.getDesignation())) {
                salary = 70000;
            } else if ("Developer".equalsIgnoreCase(emp.getDesignation())) {
                salary = 40000;
            } else if ("Tester".equalsIgnoreCase(emp.getDesignation())) {
                salary = 30000;
            }
            System.out.println("Credited Rs. " + salary + " to " + emp.getName() + " (" + emp.getDesignation() + ")");
        }
    }
}

3. Target Interface: ITarget

public interface ITarget {
    void processCompanySalary(String[][] employeesArray);
}

4. Class Adapter: EmployeeAdapter

Notice how EmployeeAdapter extends ThirdPartyBillingSystem (inheritance) instead of holding an instance:

import java.util.ArrayList;
import java.util.List;

public class EmployeeAdapter extends ThirdPartyBillingSystem implements ITarget {

    @Override
    public void processCompanySalary(String[][] employeesArray) {
        List<Employee> employeeList = new ArrayList<>();

        for (String[] empData : employeesArray) {
            int id = Integer.parseInt(empData[0]);
            String name = empData[1];
            String designation = empData[2];
            employeeList.add(new Employee(id, name, designation));
        }

        // Direct call to inherited superclass method
        processSalary(employeeList);
    }
}

5. Client: HumanResourceSystem

public class HumanResourceSystem {

    public static String[][] getEmployees() {
        return new String[][] {
            {"101", "Dave", "Team Leader"},
            {"102", "Peter", "Developer"},
            {"103", "Raj", "Developer"},
            {"104", "Rahul", "Tester"}
        };
    }

    public static void main(String[] args) {
        ITarget target = new EmployeeAdapter();
        String[][] employeesArray = getEmployees();
        
        System.out.println("HR System passing employee array to adapter...\n");
        target.processCompanySalary(employeesArray);
    }
}

Console Output

HR System passing employee array to adapter...

Credited Rs. 70000 to Dave (Team Leader)
Credited Rs. 40000 to Peter (Developer)
Credited Rs. 40000 to Raj (Developer)
Credited Rs. 30000 to Rahul (Tester)

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=0WDACH00TFk

Click the below Image to Enlarge

Adapter Pattern – Implementation [Class Adapter]





















Adapter Pattern – Implementation [Class Adapter] - Class Diagram

























Employee.java


public class Employee
{
private int    empId;
private String name;
private String designation;

public Employee( int empId, String name, String designation )
{
super();
this.empId = empId;
this.name = name;
this.designation = designation;
}

public int getEmpId()
{
return empId;
}

public void setEmpId( int empId )
{
this.empId = empId;
}

public String getName()
{
return name;
}

public void setName( String name )
{
this.name = name;
}

public String getDesignation()
{
return designation;
}

public void setDesignation( String designation )
{
this.designation = designation;
}

@Override
public String toString()
{
return "Employee [empId=" + empId + ", name=" + name + ", designation=" + designation + "]";
}

}

ThirdPartyBillingSystem.java


import java.util.ArrayList;

/*
 * ThirdPartyBillingSystem accepts employees information as a List to process each employee salary
 */
public class ThirdPartyBillingSystem
{
public void processSalary( ArrayList<Employee> employeeList )
{
for( Employee employee : employeeList )
{
System.out.print("\n"+employee.toString()+" : ");
if( employee.getDesignation().equalsIgnoreCase("Team Leader") )
{
System.out.println("70000Rs Salary credited to " + employee.getName() + " Account\n");
}
else if( employee.getDesignation().equalsIgnoreCase("Developer") )
{
System.out.println("40000Rs Salary credited to " + employee.getName() + " Account\n");
}
else if( employee.getDesignation().equalsIgnoreCase("Tester") )
{
System.out.println("30000Rs Salary credited to " + employee.getName() + " Account\n");
}
}
}

}

ITarget.java

public interface ITarget
{
public void processCompanySalary(String[][] employeeInfo);
}

EmployeeAdapter.java


import java.util.ArrayList;

public class EmployeeAdapter extends ThirdPartyBillingSystem implements ITarget
{

/*
* This Adapter method converts String Array employee information to
* ArrayList of Employees
*/

@Override
public void processCompanySalary( String[][] employeeInfo )
{
String empId = null;
String name = null;
String designation = null;
ArrayList<Employee> employeeList = new ArrayList<Employee>();
for( int i = 0; i < employeeInfo.length; i++ )
{

for( int j = 0; j < employeeInfo[i].length; j++ )
{
if( j == 0 )
{
empId = employeeInfo[i][j];
}
else if( j == 1 )
{
name = employeeInfo[i][j];
}
else
{
designation = employeeInfo[i][j];
}
}
employeeList.add(new Employee(Integer.parseInt(empId), name, designation));

}

System.out.println("Adapter converted Array of Employee to ArrayList of Employee : \n"+employeeList+"\n"+
"then call the processSalary method inherited from the ThirdPartyBillingSystem for processing the employee salary");
processSalary(employeeList);

}

}

HumanResourceSystem.java


/*
 * Client System which has employee information as String Array
 *
 */

public class HumanResourceSystem
{

public static String[][] getEmployees()
{
String[][] employees = new String[4][];

employees[0] = new String[] { "100", "Dave", "Team Leader" };
employees[1] = new String[] { "101", "Ram", "Developer" };
employees[2] = new String[] { "102", "Raj", "Developer" };
employees[3] = new String[] { "103", "Rahul", "Tester" };

return employees;
}

public static void main( String args[] )
{

ITarget target = new EmployeeAdapter();
System.out.println("HR system passes employee string array to Adapter\n");
target.processCompanySalary(getEmployees());

}
}

Output


HR system passes employee string array to Adapter

Adapter converted Array of Employee to ArrayList of Employee :
[Employee [empId=100, name=Dave, designation=Team Leader], Employee [empId=101, name=Ram, designation=Developer], Employee [empId=102, name=Raj, designation=Developer], Employee [empId=103, name=Rahul, designation=Tester]]
then call the processSalary method inherited from the ThirdPartyBillingSystem for processing the employee salary

Employee [empId=100, name=Dave, designation=Team Leader] : 70000Rs Salary credited to Dave Account


Employee [empId=101, name=Ram, designation=Developer] : 40000Rs Salary credited to Ram Account


Employee [empId=102, name=Raj, designation=Developer] : 40000Rs Salary credited to Raj Account


Employee [empId=103, name=Rahul, designation=Tester] : 30000Rs Salary credited to Rahul Account




Adapter Pattern – Implementation [Object Adapter]

🚀 Enjoying Java Tutorials?

Subscribe to Ram N Java for clean, beginner-friendly core Java tutorials and interview prep!

🔔 Subscribe to Ram N Java

Introduction

The Adapter Design Pattern allows incompatible interfaces to work together without modifying existing code. There are two primary approaches to implement this pattern: Object Adapter (using composition) and Class Adapter (using inheritance). In this tutorial, we implement the Object Adapter pattern using a real-world scenario where an existing Human Resource (HR) System integrates with a Third-Party Billing System.

The Incompatibility Problem

  • Client (HR System): Supplies employee details in a two-dimensional String[][] array format.
  • Adaptee (Third-Party Billing System): Only accepts a List<Employee> in its processSalary() method.

Neither codebase should be altered. In the Object Adapter approach, the adapter holds a reference (composition) to the adaptee instance, converts the String[][] array into a List<Employee>, and delegates the call.

Object Adapter Role Mapping

Pattern Role Component in Example Role Description
Client HumanResourceSystem Provides employee records as a String[][]
Target Interface ITarget Declares processCompanySalary(String[][])
Adaptee ThirdPartyBillingSystem Provides processSalary(List<Employee>)
Object Adapter EmployeeAdapter Implements ITarget and holds a reference to ThirdPartyBillingSystem

Step-by-Step Java Implementation

1. The Employee Model Class

public class Employee {
    private int empId;
    private String name;
    private String designation;

    public Employee(int empId, String name, String designation) {
        this.empId = empId;
        this.name = name;
        this.designation = designation;
    }

    public int getEmpId() { return empId; }
    public String getName() { return name; }
    public String getDesignation() { return designation; }
}

2. Adaptee: ThirdPartyBillingSystem

import java.util.List;

public class ThirdPartyBillingSystem {
    public void processSalary(List<Employee> employeeList) {
        for (Employee emp : employeeList) {
            int salary = 0;
            if ("Team Leader".equalsIgnoreCase(emp.getDesignation())) {
                salary = 70000;
            } else if ("Developer".equalsIgnoreCase(emp.getDesignation())) {
                salary = 40000;
            } else if ("Tester".equalsIgnoreCase(emp.getDesignation())) {
                salary = 30000;
            }
            System.out.println("Credited Rs. " + salary + " to " + emp.getName() + " (" + emp.getDesignation() + ")");
        }
    }
}

3. Target Interface: ITarget

public interface ITarget {
    void processCompanySalary(String[][] employeesArray);
}

4. Object Adapter: EmployeeAdapter

Notice how EmployeeAdapter maintains an instance variable reference (composition) to ThirdPartyBillingSystem:

import java.util.ArrayList;
import java.util.List;

public class EmployeeAdapter implements ITarget {

    // Object composition: holds a reference to the Adaptee
    private ThirdPartyBillingSystem thirdPartyBillingSystem = new ThirdPartyBillingSystem();

    @Override
    public void processCompanySalary(String[][] employeesArray) {
        List<Employee> employeeList = new ArrayList<>();

        for (String[] empData : employeesArray) {
            int id = Integer.parseInt(empData[0]);
            String name = empData[1];
            String designation = empData[2];
            employeeList.add(new Employee(id, name, designation));
        }

        // Delegate to the composed Adaptee instance
        thirdPartyBillingSystem.processSalary(employeeList);
    }
}

5. Client: HumanResourceSystem

public class HumanResourceSystem {

    public static String[][] getEmployees() {
        return new String[][] {
            {"101", "Dave", "Team Leader"},
            {"102", "Peter", "Developer"},
            {"103", "Raj", "Developer"},
            {"104", "Rahul", "Tester"}
        };
    }

    public static void main(String[] args) {
        ITarget target = new EmployeeAdapter();
        String[][] employeesArray = getEmployees();
        
        System.out.println("HR System passing employee array to adapter...\n");
        target.processCompanySalary(employeesArray);
    }
}

Console Output

HR System passing employee array to adapter...

Credited Rs. 70000 to Dave (Team Leader)
Credited Rs. 40000 to Peter (Developer)
Credited Rs. 40000 to Raj (Developer)
Credited Rs. 30000 to Rahul (Tester)

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=TMFJ1Zy2sDc

Click the below Image to Enlarge

Adapter Pattern – Implementation [Object Adapter]





















Adapter Pattern – Implementation [Object Adapter] - Class Diagram


























Employee.java

public class Employee
{
private int    empId;
private String name;
private String designation;

public Employee( int empId, String name, String designation )
{
super();
this.empId = empId;
this.name = name;
this.designation = designation;
}

public int getEmpId()
{
return empId;
}

public void setEmpId( int empId )
{
this.empId = empId;
}

public String getName()
{
return name;
}

public void setName( String name )
{
this.name = name;
}

public String getDesignation()
{
return designation;
}

public void setDesignation( String designation )
{
this.designation = designation;
}

@Override
public String toString()
{
return "Employee [empId=" + empId + ", name=" + name + ", designation=" + designation + "]";
}

}

ThirdPartyBillingSystem.java

import java.util.ArrayList;

/*
 * ThirdPartyBillingSystem accepts employees information as a List to process each employee salary
 */
public class ThirdPartyBillingSystem
{
public void processSalary( ArrayList<Employee> employeeList )
{
for( Employee employee : employeeList )
{
System.out.print("\n"+employee.toString()+" : ");
if( employee.getDesignation().equalsIgnoreCase("Team Leader") )
{
System.out.println("70000Rs Salary credited to " + employee.getName() + " Account\n");
}
else if( employee.getDesignation().equalsIgnoreCase("Developer") )
{
System.out.println("40000Rs Salary credited to " + employee.getName() + " Account\n");
}
else if( employee.getDesignation().equalsIgnoreCase("Tester") )
{
System.out.println("30000Rs Salary credited to " + employee.getName() + " Account\n");
}
}
}

}

ITarget.java

public interface ITarget
{
public void processCompanySalary(String[][] employeeInfo);
}


EmployeeAdapter.java

import java.util.ArrayList;

public class EmployeeAdapter implements ITarget
{
ThirdPartyBillingSystem thirdPartyBillingSystem =new ThirdPartyBillingSystem();

/*
* This Adapter method converts String Array employee information to ArrayList of Employees
*
*/

@Override
public void processCompanySalary( String[][] employeeInfo )
{
String empId = null;
String name = null;
String designation = null;
ArrayList<Employee> employeeList = new ArrayList<Employee>();
for( int i = 0; i < employeeInfo.length; i++ )
{

for( int j = 0; j < employeeInfo[i].length; j++ )
{
if( j == 0 )
{
empId = employeeInfo[i][j];
}
else if( j == 1 )
{
name = employeeInfo[i][j];
}
else
{
designation = employeeInfo[i][j];
}
}
employeeList.add(new Employee(Integer.parseInt(empId), name, designation));

}

System.out.println("Adapter converted Array of Employee to ArrayList of Employee : \n"+employeeList+"\n"+
"then delegate to the ThirdPartyBillingSystem for processing the employee salary");
thirdPartyBillingSystem.processSalary(employeeList);


}

}


HumanResourceSystem.java

/*
 * Client System which has employee information as String Array
 *
 */

public class HumanResourceSystem
{

public static String[][] getEmployees()
{
String[][] employees = new String[4][];

employees[0] = new String[] { "100", "Dave", "Team Leader" };
employees[1] = new String[] { "101", "Ram", "Developer" };
employees[2] = new String[] { "102", "Raj", "Developer" };
employees[3] = new String[] { "103", "Rahul", "Tester" };

return employees;
}

public static void main( String args[] )
{

ITarget target = new EmployeeAdapter();
System.out.println("HR system passes employee string array to Adapter\n");
target.processCompanySalary(getEmployees());

}
}


Output

HR system passes employee string array to Adapter

Adapter converted Array of Employee to ArrayList of Employee :
[Employee [empId=100, name=Dave, designation=Team Leader], Employee [empId=101, name=Ram, designation=Developer], Employee [empId=102, name=Raj, designation=Developer], Employee [empId=103, name=Rahul, designation=Tester]]
then delegate to the ThirdPartyBillingSystem for processing the employee salary

Employee [empId=100, name=Dave, designation=Team Leader] : 70000Rs Salary credited to Dave Account


Employee [empId=101, name=Ram, designation=Developer] : 40000Rs Salary credited to Ram Account


Employee [empId=102, name=Raj, designation=Developer] : 40000Rs Salary credited to Raj Account


Employee [empId=103, name=Rahul, designation=Tester] : 30000Rs Salary credited to Rahul Account


See also:

  • Adapter Design pattern - Introduction
  • Adapter Design Pattern - Real Time Exmaple(Translator)
  • Adapter Design pattern - Real Time Example (Card Reader)
  • Adapter Design pattern - Real Time Example (Mobile Charger)
  • Adapter Design pattern - Real Time Example (Universal Adaptor)
  • Adapter Design pattern - Real Time Example [JDBC Driver]
  • Adapter Design pattern - Class diagram
  • Adapter Design Pattern - Sequence diagram
  • Adapter Design Pattern - Implementation [Language Translator]
  • Adapter Pattern - Implementation [Class Adapter]
  • Adapter Design Pattern - Implementation [Mobile Charger]
  • Adapter Design Pattern - Key Points
  • All Design Patterns Links
  • Saturday, 2 November 2013

    Adapter Design Pattern – Implementation [Language Translator]

    🚀 Enjoying Java Tutorials?

    Subscribe to Ram N Java for clean, beginner-friendly core Java tutorials and interview prep!

    🔔 Subscribe to Ram N Java

    Introduction

    The Adapter Design Pattern is a structural design pattern that allows classes with incompatible interfaces to collaborate. A very natural real-world metaphor for this pattern is a Language Translator: imagine a person who speaks English wanting to communicate with someone who speaks French. Without an intermediary, direct communication is impossible. A translator acts as an adapter, listening to English, translating it to French, and vice versa.

    Adapter Pattern Mapping

    Pattern Role Component in Example Description
    Client EnglishSpeaker Understands and speaks English words only
    Target Interface ITarget Defines the interface expected by the client (e.g., translateAndTalk())
    Adaptee FrenchSpeaker Existing class that understands only French
    Adapter TranslatorAdapter Translates messages between English and French seamlessly

    Java Code Implementation

    1. Adaptee: FrenchSpeaker

    public class FrenchSpeaker {
        public void speakFrench(String words) {
            System.out.println("French speaker receives: " + words);
        }
    
        public String replyInFrench() {
            return "Très bien, merci!";
        }
    }

    2. Target Interface: ITarget

    public interface ITarget {
        void speakEnglish(String words);
        String receiveReplyInEnglish();
    }

    3. Adapter: TranslatorAdapter

    public class TranslatorAdapter implements ITarget {
        private FrenchSpeaker frenchSpeaker = new FrenchSpeaker();
    
        @Override
        public void speakEnglish(String words) {
            System.out.println("Adapter translates English: \"" + words + "\" to French");
            String frenchTranslation = convertToFrench(words);
            frenchSpeaker.speakFrench(frenchTranslation);
        }
    
        @Override
        public String receiveReplyInEnglish() {
            String frenchReply = frenchSpeaker.replyInFrench();
            System.out.println("Adapter receives French reply: \"" + frenchReply + "\"");
            return convertToEnglish(frenchReply);
        }
    
        private String convertToFrench(String englishWords) {
            if ("Hello, how are you?".equalsIgnoreCase(englishWords)) {
                return "Bonjour, comment allez-vous?";
            }
            return "Bonjour!";
        }
    
        private String convertToEnglish(String frenchWords) {
            if ("Très bien, merci!".equalsIgnoreCase(frenchWords)) {
                return "Very well, thank you!";
            }
            return "Thank you!";
        }
    }

    4. Client: EnglishSpeaker

    public class EnglishSpeaker {
        public static void main(String[] args) {
            ITarget translator = new TranslatorAdapter();
    
            System.out.println("English Speaker says: Hello, how are you?\n");
            translator.speakEnglish("Hello, how are you?");
    
            System.out.println();
            String reply = translator.receiveReplyInEnglish();
            System.out.println("English Speaker hears: " + reply);
        }
    }

    Console Output

    English Speaker says: Hello, how are you?
    
    Adapter translates English: "Hello, how are you?" to French
    French speaker receives: Bonjour, comment allez-vous?
    
    Adapter receives French reply: "Très bien, merci!"
    English Speaker hears: Very well, thank you!

    Related Tutorials from Ram N Java


    Click here to watch in Youtube : https://www.youtube.com/watch?v=oudJQOQU-i8

    Click the below Image to Enlarge
    Adapter Design Pattern – Implementation [Language Translator]






















    Adapter Design Pattern – Implementation [Language Translator] - Class Diagram



























    ITarget.java

    public interface ITarget
    {
    public String translateAndTellToOtherPerson(String words,String convertToWhichLanguage);
    }

    John.java

    import java.util.HashMap;

    /*
     *  John can speak and understand English and French,he acts as a Adapter or Translator
     */
    public class John implements ITarget
    {

    static HashMap<String, String> englishFrenchMap = new HashMap<String, String>();
    static HashMap<String, String> frenchEnglishMap = new HashMap<String, String>();
    David david = new David();
    Rohit rohit =new Rohit();

    static
    {
    englishFrenchMap.put("how are you?", "comment allez-vous?");
    englishFrenchMap.put("I am in USA", "Je suis aux Etats-Unis");
    frenchEnglishMap.put("Je suis très bien", "I am fine");
    frenchEnglishMap.put("où êtes-vous?", "where are you?");

    }

    @Override
    public String translateAndTellToOtherPerson( String words, String convertToWhichLanguage )
    {
    if( convertToWhichLanguage.equalsIgnoreCase("English") )
    {

    String englishWords = convertToEnglish(words);
    System.out.println("\nJohn Converted \"" + words + " \" to \"" + englishWords
                   + " and send the question to David");
    String englishWordsReply = david.answerFortheQuestion(englishWords);
    System.out.println("John Got reply from David in English like : " + "\"" + englishWordsReply
                   + "\"");
    String frenchConverted = convertToFrench(englishWordsReply);
    System.out.println("John Converted " + "\"" + englishWordsReply + "\"" + " to " + "\""
                   + frenchConverted + "\"" + " and send back to Rohit\n");
    return frenchConverted;

    }
    else if( convertToWhichLanguage.equalsIgnoreCase("French") )

    {
    String frenchWords = convertToFrench(words);
    System.out.println("\nJohn Converted \"" + words + " \" to \"" + frenchWords
                   + " and send the question to Rohit");
    String frenchWordsReply =rohit.answerFortheQuestion(frenchWords);
    System.out.println("John Got reply from Rohit in French like : " + "\"" + frenchWordsReply
                   + "\"");
    String englishConverted = convertToEnglish(frenchWordsReply);
    System.out.println("John Converted " + "\"" + frenchWordsReply + "\"" + " to " + "\""
                   + englishConverted + "\"" + " and send back to David\n");
    return englishConverted;

    }

    return "Sorry Cannot Covert";
    }

    public String convertToFrench( String words )
    {
    return englishFrenchMap.get(words);
    }

    public String convertToEnglish( String words )
    {
    return frenchEnglishMap.get(words);
    }

    }


    EnglishSpeaker.java

    public interface EnglishSpeaker
    {
    public String askQuestion( String words );
    public String answerFortheQuestion( String words );

    }

    David.java
    /*
     * He is from USA, So he can speak and understand only English
     */
    public class David implements EnglishSpeaker
    {

    public static void main( String args[] )
    {
    String replyFromRohit = new David().askQuestion("how are you?");
    System.out.println("Reply From Rohit [French Speaker can Speak and Understand only French] :  " + replyFromRohit);
    }

    @Override
    public String askQuestion( String words )
    {
    System.out.println("Question Asked by David [English Speaker and Can understand only English] : " +words);
    ITarget target = new John();
    String replyFromRohit = target.translateAndTellToOtherPerson(words, "French");
    return replyFromRohit;
    }

    @Override
    public String answerFortheQuestion( String words )
    {
    String reply = null;
    if( words.equalsIgnoreCase("where are you?") )
    {
    reply = "I am in USA";
    }
    return reply;
    }

    }


    FrenchSpeaker.java

    public interface FrenchSpeaker
    {
    public String askQuestion( String words );
    public String answerFortheQuestion( String words );

    }


    Rohit.java

    /*
     * He is from France, So he can speak and understand only French
     */
    public class Rohit implements FrenchSpeaker
    {

    public static void main( String args[] )
    {
    String replyFromDavid = new Rohit().askQuestion("où êtes-vous?");
    System.out.println("Reply From David [English Speaker can Speak and Understand only English] :  " + replyFromDavid);
    }

    @Override
    public String askQuestion( String words )
    {
    System.out.println("Question Asked by Rohit [French Speaker and Can understand only French] : " +words);
    ITarget target = new John();
    String replyFromDavid = target.translateAndTellToOtherPerson(words, "English");
    return replyFromDavid;
    }

    @Override
    public String answerFortheQuestion( String words )
    {
    String reply = null;
    if( words.equalsIgnoreCase("comment allez-vous?") )
    {
    reply = "Je suis très bien";
    }
    return reply;
    }

    }

    Output

    David asks Question to Rohit

    Question Asked by David [English Speaker and Can understand only English] : how are you?

    John Converted "how are you? " to "comment allez-vous? and send the question to Rohit
    John Got reply from Rohit in French like : "Je suis très bien"
    John Converted "Je suis très bien" to "I am fine" and send back to David

    Reply From Rohit [French Speaker can Speak and Understand only French] :  I am fine

    Rohit asks Question to David

    Question Asked by Rohit [French Speaker and Can understand only French] : où êtes-vous?

    John Converted "où êtes-vous? " to "where are you? and send the question to David
    John Got reply from David in English like : "I am in USA"
    John Converted "I am in USA" to "Je suis aux Etats-Unis" and send back to Rohit

    Reply From David [English Speaker can Speak and Understand only English] :  Je suis aux Etats-Unis

    Tutorials