Intent

The intent of the adapter design pattern is to convert the interface of a class into another interface that the client expects. Adapter lets classes work together that couldn't otherwise bexause of incompatible interfaces.

Motivation

The Adapter Design Patterns intent does a good job of explaining exactly what the design pattern does. A great way to think of it is to think of the power adapters that you use whenever you go to another country. These power adapters change the plug from your countries standard plug into one that the new countries sockets accepts and thus makes your appliances useable.

This analogy can be directly transfered over to a software development style of thinking. Say you have a legacy piece of software that produces the results you need but doesn't adhere to the correct interface. By using an adapter class we can call the old functionality from the new adapter class that implements the interface that we expect.

This is perfect in scenarios where we cannot change say a frameworks code but need a class to conform to an already defined interface. This essentially works as a middleman that takes in your request and processes them in a way that would be meaningful to you.

Applicability

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, this is, classes that don't necessarily havev compatible interfaces.
  • 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 interfaces of its parent class. 

Implementation Example:

Character Interface:

public interface Character {

	public void attack();
	public double getHealth();
	public void setHealth(double newHealth);
	
}

Player Class

public class Player implements Character{

	public double health = 100;
	public int ammo = 10;
	
	@Override
	public void attack() {
		System.out.println("Attack");
	}

	@Override
	public double getHealth() {
		return this.health;
	}

	@Override
	public void setHealth(double newHealth) {
		this.health = newHealth;
	}

}

Enemy Class


public class Enemy {
	
	public double armour = 150;
	
	public void destroy(){
		System.out.println("Destroy");
	}
	
	public double getArmour(){
		return this.armour;
	}
	
	public void setArmour(double newArmour){
		this.armour = newArmour;
	}

}

CharacterAdapter

public class CharacterAdapter implements Character{

	Enemy mainEnemy;
	
	public CharacterAdapter(Enemy newEnemy){
		this.mainEnemy = newEnemy;
	}
	
	@Override
	public void attack() {
		this.mainEnemy.destroy();
	}

	@Override
	public double getHealth() {
		return this.mainEnemy.getArmour();
	}

	@Override
	public void setHealth(double newHealth) {
		this.mainEnemy.setArmour(newHealth);
	}
}

Client(main) class

public class Client {
	
	public static void main(String args[]){
		
		Player player1 = new Player();
		
		Enemy enemy1 = new Enemy();
		
		CharacterAdapter charAdapter = new CharacterAdapter(enemy1);
		
		player1.attack();
		charAdapter.attack();
		
		player1.setHealth(150.00);
		System.out.println("Player Health: " + player1.getHealth());
		
		charAdapter.setHealth(200.00);
		System.out.println("Enemy Health: " + charAdapter.getHealth());
		
	}

}