2015.08.06 22:45

스트레티지 패턴(Strategy Pattern)이란 알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다.

스트래티지를 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.

라고 Head Firest Design Pattern 책에서 정의한다.

 

알고리즘군을 정의한다는 말이 조금 어려운데 그냥 행동들을 정의하는 클래스를 만든다고 생각하면 된다.

일단 아래의 자료들을 보며 스트레티지 패턴(Strategy Pattern)이 어떨때 사용되는 것인지 생각해보자.

 

개들이 짖고 뛰어다니고 수영하고 하는 시뮬레이션 게임이 있다고 생각해보자.

개를 정의하는 클래스는 간략하게 아래와같이 디자인 할 수 있을 것이다. 

그런데 이 개들에게 날아다니는 기능이 추가되었다고 생각해보자. 어떻게 기능을 추가할 수 있을까?


 

가장 쉽게 생각할 수 있는 방법이 Dog 클래스에 Fly()메서드를 추가하는 것이다.

이렇게 하면 Dog를 상속받은 모든 클래스가 나는 기능을 가질 것이다.

하지만 모든 개가 날아다니는 것이 아니라 어떤 개는 날고 어떤 개는 못난다면 어떨까?

또는 어떤 개는 날개를 달아 날지만 어떤 개는 프로펠러나 로켓을 통해 날아다닌다면??



물론 오버라이딩을 통해 해결할 수 있고 이러한 방법도 나쁘다고 할 수 없다.

 

하지만 프로젝트의 규모가 점점 커지면서 많은 기능이 추가된다면 어떨까?

우선적으로 Dog클래스의 코드가 점점 많아질 것이고 추가된 기능을 사용하지 않는 자식들도 있을 것이다.


 

 

여기서 뭔가 잘못되었다는 것을 깨달았으니 리펙토링을 시도해보자.

 

Dog의 속성을 다르게 하는 요소들을 분리하여 캡슐화해야 한다는 것은 떠오르는데 막상 클래스를 디자인하려니 이것 저것 거슬리는 것이 한 두가지가 아니다.

여러 기능을 갖기 위해 다중 상속을 하는 것도 생각해보았지만 코드 중복 문제도 심각하고 절대 빠져나올 수 없는 구렁텅이로 빠지는 느낌이다.

 

일단 어떻게든 캡슐화를 해야한다. 어떻게 해야 할까?

 

방법은 바로 행동(알고리즘군)에 따라 분리하는 것이다.

클래스를 일반적으로 어떤 대상을 나타내기 위해서만 디자인해왔다면 이것이 굉장히 어색하게 느껴질 수 있지만 그렇게 못할 것도 없다.

 

행동에 따라 분리하고 인터페이스를 중점으로 클래스를 디자인해보자.

 

분리된 클래스의 디자인은 다음과 같이 나타낼 수 있다.

 

상속만을 생각할 때는 막막했지만 Has A 관계로 눈을 돌리면 코드는 매우 유연해진다.

 

위와 같은 디자인의 큰 장점 중 하나는 setter를 이용하여 실행 타임에 행동을 변경하는 것이 가능하다는 것이다.

처음에 디자인한 것처럼 Super 클래스에 매서드를 몰아 넣고 모든 경우를 오버라이딩할 때에는 이런 유연함을 가질 수 없었다.

 

지금까지 설명한 내용을 기반으로 작성한 C++ 소스 코드이다.

Duck 클래스는 이제 각종 행동을 가상 함수의 형태로 갖는 대신 분리된 인터페이스를 Has하는 형태로 바뀌었다.

 

인터페이스는 다음과 같이 분리하였기 때문에 구현부가 아무리 바뀌고 확장된다고 하더라도 Duck 클래스에는 영향을 미치지 않는다.

 

또한 메인문에서 보는 바와 같이 실행시간에 행동의 속성을 바꾸는 것도 가능하다..




 

 

 

자료에 첨부된 소스 코드는 디자인 패턴의 개념을 참고하여 C++로 구현한 것이므로 잘못된 점이 있을 수 있습니다.

문제점이 발견될 시 피드백 부탁드립니다.

 

[참고 문헌 : 에릭 프리먼, 서환수 역, Head First Design Patterns ]


출처 : http://blog.naver.com/jidon333

신고
Posted by 우엉 여왕님!! ghostkyow

티스토리 툴바