어댑터 패턴은 클래스를 바로 사용할 수 없는 경우에 유용하다. 예를 들어, 다른 곳에서 개발되었거나 수정할 수 없는 클래스를 사용할 때, 중간에서 변환 역할을 해주는 클래스가 필요하다. 어댑터 패턴은 이런 상황에서 호환되지 않은 인터페이스를 사용하는 클라이언트를 그대로 활용할 수 있게 해준다. 또한, 향후 인터페이스가 바뀌더라도 변경 내역은 어댑터에 캡슐화되므로 클라이언트 코드를 변경할 필요가 없다.
아이폰의 이어폰을 생각해보자. 일반적인 이어폰 잭을 아이폰에 사용하려면, 잭 자체가 맞지 않는다. 따라서 우리는 어댑터를 따로 구매해서 연결해야 이런 이어폰들을 사용할 수 있다. 이처럼 어댑터는 필요로 하는 인터페이스로 바꿔주는 역할을 한다.
이처럼 업체에서 제공한 클래스가 기존 시스템에 맞지 않으면, 기존 시스템을 수정할 것이 아니라 어댑터를 활용해 유연하게 해결할 수 있다.
만약 자동차 객체가 부족해서 보트 객체를 대신 사용해야 한다면, 두 객체는 인터페이스가 다르므로 바로 보트 객체를 사용하는 것은 불가능하다. 따라서 보트 어댑터를 생성해서 활용해야 한다.
package AdapterPattern;
public interface Car {
public void drive();
public void honk();
}
Car
인터페이스는 drive
와 honk
메서드를 정의하고 있다. 이는 자동차의 기능을 나타낸다.package AdapterPattern;
public interface Boat {
public void sail();
public void soundHorn();
}
package AdapterPattern;
public class SpeedBoat implements Boat {
@Override
public void sail() {
System.out.println("The boat is sailing");
}
@Override
public void soundHorn() {
System.out.println("Boat horn sounds");
}
}
SpeedBoat
클래스는 Boat
인터페이스를 구현하며, sail
과 soundHorn
메서드를 오버라이드하여 실제 보트의 동작을 정의하고 있다.package AdapterPattern;
public class BoatAdapter implements Car {
Boat boat;
public BoatAdapter(Boat boat) {
this.boat = boat;
}
@Override
public void drive() {
boat.sail();
}
@Override
public void honk() {
boat.soundHorn();
}
}
BoatAdapter
클래스는 Car
인터페이스를 구현하며, Boat
객체를 인스턴스 변수로 가진다.drive
메서드는 boat.sail()
을 호출하여 보트의 sail
메서드를 실행하고, honk
메서드는 boat.soundHorn()
을 호출하여 보트의 soundHorn
메서드를 실행한다.Boat
객체를 Car
객체처럼 사용할 수 있게 된다.package AdapterPattern;
public class AdapterTest {
public static void main(String[] args) {
SportsCar car = new SportsCar();
SpeedBoat boat = new SpeedBoat();
Car boatAdapter = new BoatAdapter(boat);
System.out.println("The boat says...");
boat.sail();
boat.soundHorn();
System.out.println("The Car says...");
testCar(car);
System.out.println("The BoatAdapter says...");
testCar(boatAdapter);
}
public static void testCar(Car car) {
car.drive();
car.honk();
}
}
AdapterTest
클래스는 main
메서드를 통해 어댑터 패턴을 테스트한다.SportsCar
객체와 SpeedBoat
객체를 생성하고, SpeedBoat
객체를 BoatAdapter
로 감싸 Car
인터페이스로 변환한다.testCar
메서드는 Car
인터페이스를 인자로 받아 drive
와 honk
메서드를 호출한다.Car
인터페이스를 구현함으로써, SpeedBoat
객체를 Car
객체처럼 사용할 수 있음을 보여준다.어댑터 패턴은 호환되지 않은 인터페이스를 사용하는 클래스를 변환하여 클라이언트가 사용할 수 있도록 해준다. 이를 통해 기존 시스템을 수정하지 않고도 새로운 클래스를 유연하게 통합할 수 있다. 어댑터 패턴은 특히 변경 가능한 인터페이스가 있을 때 유용하며, 클라이언트 코드의 안정성을 유지하면서도 다양한 클래스와의 통합을 가능하게 한다.