The Adapter Pattern

The Adapter Pattern

The adapter pattern helps establishing a communication between two different interfaces. Basically the adapter takes an existing implementation of a class and wraps it while exposing a compatible interface it can then use to communicate with the client.

Let's imagine we have an existing application which is for example a dungeon crawler game, we have an Enemy class with different actions (attack, defend etc.) which is used to create different types of enemies. We want to build now a sequel but want to re-use the exiting Enemy class without touching the existing implementation. Problem is, our client expects Enemies that can also perform a "talk" action for whatever reason. Let us have a look at the exiting implementation:

class Enemy {
    contructor(name: string, x: number, y: number, strength: number) {
        this.name = name;
        this.x = x;
        this.y = y;
        this.strength = strength;
    }
    
    public attack(target: Player) {
        // some attack logic
    }
    
    public defend() {
        // some defend logic
    }
}

// Old Enemy Types
const goblin = new Enemy("Goblin", 10, 10, 6);

To re-use the exiting implementations, we can create now an adapter class that extends the Enemy class we can then extend.

class EnemyAdapter extends Enemy {
    // silly new action
    public talk(target: Player, message:string): void {
        console.log(`Hello ${target.name}, ${message}`);
    }
}

// new enemy 
const orc = new EnemyAdapter("Orc", 10, 10, 10);

// The client can use now the new method
orc.talk(player, "I will destroy you!");