북극곰의 개발일기

8일차 어댑터 패턴





posted by purplebeen on Sat Feb 03 2018 21:01:01 GMT+0900 (KST) in JAVA


원래 순서 상으로는 커맨드(Command) 패턴이 먼저 나와야 하지만 컴퓨터 포맷으로 인해 그동안 썼던 예제가 날라가서...

다음에 올리는 걸로 하고 일단 어댑터 패턴부터 먼저 하기로 한다.

어댑터 패턴(Adpater Pattern) : 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다. 어댑터를 이용하면 인터페이스의 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있다.

예를 들어, 우리가 처음에 스트래티지 패턴을 사용할때 썼었던 Duck Interface를 생각해보자.

public interface Duck {
	public void quack();
	public void fly();
}

이는 인터페이스이기 때문에 어딘가에서 구현(implements) 해줘야 한다. 이를 MallardDuck(물 오리) 라는 클래스에서 구현시켜 보자.

public class MallardDuck implements Duck{

	@Override
	public void quack() {
		// TODO Auto-generated method stub
		System.out.println("Quack");
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("I'm flying!!");
	}

}

자 그러면 이제 더이상 오리가 아니라 가금류를 만들어야 되는 상황이 되었다고 생각해보자. 가금류에 맞는 인터페이스를 새로 만들어야 한다.

public interface Turkey {
	public void gobble();
	public void fly();
}

그러면 이를 구현하는 WildTurkey라는 클래스를 만들어 보자.

public class WildTurkey implements Turkey{

	@Override
	public void gobble() {
		// TODO Auto-generated method stub
		System.out.println("Gobble gobble");
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("I'm flying a short distance");
	}

}

근데 이런 상황에서 Turkey 객체가 모자라서 Duck객체를 대신 사용할 수 밖에 없는 상황이 발생하면 어떻게 해야될까?

우리는 이런 상황을 위해서 Adapter Pattern을 사용한다.

public class TurkeyAdapter implements Duck{
	Turkey turkey;
	public TurkeyAdapter(Turkey turkey) {
		this.turkey = turkey;
	}

	@Override
	public void quack() {
		// TODO Auto-generated method stub
		turkey.gobble();
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		for(int i = 0 ; i < 5; i++) {
			turkey.fly();
		}
	}

}

생성자(Constructor)에서 Turkey 객체를 인자값으로 받아와 TurkeyAdapter의 Turkey 인스턴스에 넣어주고,

Duck의 quack에서 Turkey객체의 gobble 메소드를 실행시켜 주었고 Duck의 fly()메소드에서 Turkey의 fly() 메소드를 호출시키는 것을 볼 수 있다.

그럼 이렇게 했을 때의 결과가 그냥 Turkey 객체를 생성했을 때와의 결과와 어떻게 다를지 실행시켜보자.


public class DuckTestDrive {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MallardDuck duck = new MallardDuck();
		
		WildTurkey turkey = new WildTurkey();
		Duck turkeyAdapter = new TurkeyAdapter(turkey);
		
		System.out.println("the trukey says...");
		turkey.gobble();
		turkey.fly();
		
		System.out.println("\nThe Duck says....");
		testDuck(duck);
		
		System.out.println("\nThe TurkeyAdapter Says...");
		testDuck(turkeyAdapter);
	}
	static void testDuck(Duck duck) {
		duck.quack();
		duck.fly();
	}

}

Turkey객체를 직접 생성하여 메소드르 실행시켰을 때와 어댑터 패턴을 이용하여 메소드를 실행시켰을때의 결과가 같은 것을 볼 수 있다.

이처럼 어댑터 패턴은 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환시킬때 사용한다.