--- title: Adapter Pattern tags: "Design Patterns" --- ## Adapter Pattern - The Adapter Pattern is a structural design pattern that allows objects with incompatible interfaces to collaborate. - It acts as a bridge between two incompatible interfaces, making them work together. ### Example Suppose we have a system with two types of birds: Ducks and Turkeys. We want to make Ducks and Turkeys compatible with a common interface called "Duck." ### Duck and Turkey Interfaces We have a Duck interface: ```go type Duck interface { Quack() Fly() } ``` We have a Turkey interface: ```go type Turkey interface { Gobble() Fly() } ``` ### Duck and Turkey Implementations We have a MallardDuck: ```go type MallardDuck struct{} func (m *MallardDuck) Quack() { fmt.Println("Quack") } func (m *MallardDuck) Fly() { fmt.Println("I'm flying") } ``` We have a WildTurkey: ```go type WildTurkey struct{} func (w *WildTurkey) Gobble() { fmt.Println("Gobble gobble") } func (w *WildTurkey) Fly() { fmt.Println("I'm flying a short distance") } ``` ### Adapter Adapter for Turkey: ```go type TurkeyAdapter struct { turkey Turkey } func (t *TurkeyAdapter) Quack() { t.turkey.Gobble() } func (t *TurkeyAdapter) Fly() { for i := 0; i < 5; i++ { t.turkey.Fly() } } ``` ### Use the Adapter to make a Turkey compatible with a Duck ```go func main() { duck := &MallardDuck{} turkey := &WildTurkey{} turkeyAdapter := &TurkeyAdapter{turkey: turkey} fmt.Println("The Turkey says...") turkey.Gobble() // Gobble gobble turkey.Fly() // I'm flying a short distance fmt.Println("\nThe Duck says...") testDuck(duck) // Quack // I'm flying fmt.Println("\nThe TurkeyAdapter says...") testDuck(turkeyAdapter) // Gobble gobble // I'm flying a short distance // I'm flying a short distance // I'm flying a short distance // I'm flying a short distance // I'm flying a short distance } func testDuck(duck Duck) { duck.Quack() duck.Fly() } ``` ### Drone Example The interface and implementation for a Drone: ```go type Drone interface { Beep() SpinRotors() TakeOff() } type SuperDrone struct{} func (s *SuperDrone) Beep() { fmt.Println("Beep beep beep") } func (s *SuperDrone) SpinRotors() { fmt.Println("Rotors are spinning") } func (s *SuperDrone) TakeOff() { fmt.Println("Taking off") } ``` The adapter for a Drone: ```go type DroneAdapter struct { drone Drone } func (d *DroneAdapter) Quack() { d.drone.Beep() } func (d *DroneAdapter) Fly() { d.drone.SpinRotors() d.drone.TakeOff() } ``` Use the adapter to make a Drone compatible with a Duck: ```go func main() { drone := &SuperDrone{} droneAdapter := &DroneAdapter{drone: drone} fmt.Println("\nThe DroneAdapter says...") testDuck(droneAdapter) // Beep beep beep // Rotors are spinning // Taking off } ``` ### Summary - The Adapter Pattern allows us to make incompatible interfaces work together. - It promotes reusability of existing code. - It is helpful to integrate legacy or third-party code into our system.