λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
develop_en/theory

πŸ”Œ Adapter Pattern: The Magic of Connecting Incompatible Interfaces

by JSsunday 2025. 7. 14.
728x90
λ°˜μ‘ν˜•

πŸ€” What is the Adapter Pattern?

The Adapter Pattern is a structural design pattern that allows classes with incompatible interfaces to work together. Just like a power adapter you use when traveling, it serves as a bridge connecting systems with different specifications.

🎯 Key Features

  • Integration with new interfaces without modifying existing code
  • Bridge between legacy systems and new systems
  • Clean design following the Dependency Inversion Principle

🌊 Java Example: Ocean Creature Adapter

An example where various marine creatures move in different ways but are managed through a common interface.

// 🐠 Existing Fish Interface
interface Fish {
    void swim();
}

// 🦈 Shark Class
class Shark implements Fish {
    @Override
    public void swim() {
        System.out.println("🦈 Shark swims fast!");
    }
}

// πŸ™ Octopus Class (Different Interface)
class Octopus {
    public void crawl() {
        System.out.println("πŸ™ Octopus crawls on the ocean floor!");
    }
}

// πŸ”§ Octopus Adapter
class OctopusAdapter implements Fish {
    private Octopus octopus;
    
    public OctopusAdapter(Octopus octopus) {
        this.octopus = octopus;
    }
    
    @Override
    public void swim() {
        // Convert octopus crawl to swim
        octopus.crawl();
        System.out.println("πŸ’« Octopus moves like swimming!");
    }
}

// 🌊 Ocean Ecosystem Manager
class OceanManager {
    private List<Fish> marineLife = new ArrayList<>();
    
    public void addFish(Fish fish) {
        marineLife.add(fish);
    }
    
    public void makeAllSwim() {
        System.out.println("🌊 Ocean creatures are moving:");
        marineLife.forEach(Fish::swim);
    }
}

// Usage Example
public class AdapterPatternExample {
    public static void main(String[] args) {
        OceanManager ocean = new OceanManager();
        
        // Add regular fish
        ocean.addFish(new Shark());
        
        // Add octopus wrapped with adapter
        Octopus octopus = new Octopus();
        ocean.addFish(new OctopusAdapter(octopus));
        
        ocean.makeAllSwim();
    }
}

☁️ TypeScript Example: Sky Wing Adapter

An example integrating different flying methods of various creatures in the sky.

// ✈️ Existing Flight Interface
interface Flyer {
    fly(): void;
}

// πŸ¦… Eagle Class
class Eagle implements Flyer {
    fly(): void {
        console.log("πŸ¦… Eagle spreads its wings and flies!");
    }
}

// 🚁 Helicopter Class (Different Interface)
class Helicopter {
    rotate(): void {
        console.log("🚁 Helicopter rotates its rotor!");
    }
}

// πŸ”§ Helicopter Adapter
class HelicopterAdapter implements Flyer {
    private helicopter: Helicopter;
    
    constructor(helicopter: Helicopter) {
        this.helicopter = helicopter;
    }
    
    fly(): void {
        // Convert helicopter rotate to fly
        this.helicopter.rotate();
        console.log("πŸ’« Helicopter flies through the sky!");
    }
}

// 🎈 Balloon Class (Another Different Interface)
class Balloon {
    float(): void {
        console.log("🎈 Balloon floats up in the air!");
    }
}

// πŸ”§ Balloon Adapter
class BalloonAdapter implements Flyer {
    private balloon: Balloon;
    
    constructor(balloon: Balloon) {
        this.balloon = balloon;
    }
    
    fly(): void {
        // Convert balloon float to fly
        this.balloon.float();
        console.log("πŸ’« Balloon flies through the sky!");
    }
}

// ☁️ Sky Traffic Controller
class SkyController {
    private flyers: Flyer[] = [];
    
    addFlyer(flyer: Flyer): void {
        this.flyers.push(flyer);
    }
    
    makeAllFly(): void {
        console.log("☁️ Everything in the sky is flying:");
        this.flyers.forEach(flyer => flyer.fly());
    }
}

// Usage Example
const skyController = new SkyController();

// Add regular flyer
skyController.addFlyer(new Eagle());

// Add helicopter wrapped with adapter
const helicopter = new Helicopter();
skyController.addFlyer(new HelicopterAdapter(helicopter));

// Add balloon wrapped with adapter
const balloon = new Balloon();
skyController.addFlyer(new BalloonAdapter(balloon));

skyController.makeAllFly();

🌍 Python Example: Ground Movement Adapter

An example integrating movement methods of various creatures and vehicles on land.

from abc import ABC, abstractmethod

# 🚢 Existing Movement Interface
class Walker(ABC):
    @abstractmethod
    def walk(self):
        pass

# πŸ¦“ Zebra Class
class Zebra(Walker):
    def walk(self):
        print("πŸ¦“ Zebra walks on four legs!")

# 🐍 Snake Class (Different Interface)
class Snake:
    def slither(self):
        print("🐍 Snake slithers by wriggling its body!")

# πŸ”§ Snake Adapter
class SnakeAdapter(Walker):
    def __init__(self, snake: Snake):
        self.snake = snake
    
    def walk(self):
        # Convert snake slither to walk
        self.snake.slither()
        print("πŸ’« Snake moves like walking!")

# πŸš— Car Class (Another Different Interface)
class Car:
    def drive(self):
        print("πŸš— Car runs by rolling its wheels!")

# πŸ”§ Car Adapter
class CarAdapter(Walker):
    def __init__(self, car: Car):
        self.car = car
    
    def walk(self):
        # Convert car drive to walk
        self.car.drive()
        print("πŸ’« Car moves like walking!")

# πŸ€– Robot Class (Another Different Interface)
class Robot:
    def move_mechanically(self):
        print("πŸ€– Robot moves mechanically!")

# πŸ”§ Robot Adapter
class RobotAdapter(Walker):
    def __init__(self, robot: Robot):
        self.robot = robot
    
    def walk(self):
        # Convert robot move_mechanically to walk
        self.robot.move_mechanically()
        print("πŸ’« Robot moves like walking!")

# 🌍 Ground Manager
class GroundManager:
    def __init__(self):
        self.walkers = []
    
    def add_walker(self, walker: Walker):
        self.walkers.append(walker)
    
    def make_all_walk(self):
        print("🌍 Everything on the ground is moving:")
        for walker in self.walkers:
            walker.walk()

# Usage Example
if __name__ == "__main__":
    ground_manager = GroundManager()
    
    # Add regular walker
    ground_manager.add_walker(Zebra())
    
    # Add snake wrapped with adapter
    snake = Snake()
    ground_manager.add_walker(SnakeAdapter(snake))
    
    # Add car wrapped with adapter
    car = Car()
    ground_manager.add_walker(CarAdapter(car))
    
    # Add robot wrapped with adapter
    robot = Robot()
    ground_manager.add_walker(RobotAdapter(robot))
    
    ground_manager.make_all_walk()

πŸ’‘ Advantages of the Adapter Pattern

βœ… Benefits

  • Integrate new functionality without modifying existing code
  • Follow the Single Responsibility Principle
  • Maintain compatibility with legacy systems
  • Increase code reusability

⚠️ Considerations

  • May increase code complexity
  • Performance degradation with too many adapters
  • Need to modify adapters when interfaces change

🎯 When to Use?

  • When integrating legacy systems with new systems
  • When external library interfaces don't match
  • When converting between different data formats
  • When integrating communication interfaces between microservices

πŸ“š Conclusion

The Adapter Pattern is a very practical pattern in software development. Just like adapters in real life, it allows different systems to connect and create greater value.

If you're struggling with incompatible interfaces, try applying the Adapter Pattern! πŸš€


 

728x90
λ°˜μ‘ν˜•

λŒ“κΈ€