////
Search

1장 - 전략패턴

Created
2022/09/03 11:28
Tags
디자인패턴

요구사항 : 오리 시뮬레이션 게임 SimUduck

오리 시뮬레이션 게임
이 게임에는 헤엄도 치고 꽥꽤 소리도 내는 다양한 오리가 등장
추후 요구사항이 변경되어 날 수 있는 기능이 추가되어야 함
또 다른 요구사항으로 소리를 내지 못하는 오리라던지, 날지 못하는 오리 등이 추가 됨

문제를 명확하게 파악하기

달라지는 부분을 찾아서 영향을 주이 않도록 캡슐화 한다.
바뀌는 부분과 그렇지 않은 부분 분리하기

해결 방법 1 : 상속(슈퍼클래스)을 통한 해결

클래스 다이어그램
모든 오리가 꽥꽥 소리를 내고, 헤엄칠 수 있다 생각하여 이런 특성을 모두 슈퍼클래스에서 구현
해당 슈퍼클래스를 상속받은 서브클래스들은 고유한 모양을 나타내는 display메소드를 오버라이딩 해서 자신만의 특성을 만들어 낸다.

장점

단순한 요구사항 변경에 발빠르게 대응이 가능함
코드의 중복이 줄어들음 (코드의 재사용성 증가)

단점

모든 서브클래스가 슈퍼클래스의 메소드를 따르지 않는 예외가 있을 경우 메소드를 오버라이딩 해야만 한다.
슈퍼클래스에 의존하는 서브클래스는 점점더 증가할 것이고, 이후 요구사항이 변동될 시 슈퍼클래스의 수정은 곧 서브클래스의 변동을 의미한다.
즉 한번의 수정이 너무나도 많은 소스에 영향을 미치게 된다.
또한 원치않는 요구사항을 가진 서브클래스의 경우 지속적으로 의미없는 오버라이딩을 하게 된다.

해결 방법 2 : 인터페이스 분리하여 구현

클래스 다이어그램
공통으로 가지는 행동은 슈퍼클래스로, 부분적으로 가지는 행동은 인터페이스로 분리하여 구현

장점

Flyable, Quackable 인터페이스를 통해서 특정한 행동만 구현할 수 있음

단점

같은 행동을 하는 코드가 중복됨
날수있는 오리 중에서도 날아다니는 방식이 서로 다를 수 있는 문제가 있음

해결 방법 3 : 분리된 인터페이스 구현체를 따로 구분

행동을 캡슐화해 구현한 인터페이스와 구현체들
A.K.A. 전략패턴

장점

오리들이 직접 인터페이스를 구현하지 않기 때문에 코드 중복을 걱정할 필요가 없음
새로운 요구사항이 추가되면 인터페이스 구현체를 늘려주면 해결 됨
런타임 도중 동적으로 오리의 행동을 바꿀 수 있음
직정 정의한 메소드를 쓰는것이 아닌 다른 클래스에 행동을 위임함
public abstract class Duck { // 직접 구현이 아닌 Setter 혹은 생성자를 통해서 DI 받음 QuackBehavior quackBehavior; ... public void performQuack() { // 참조 객체에 행동을 위임함 quackBehavior.quack(); } }
Java
복사

정리

상속을 통한 해결은 지속적 요구사항 해결 해결에 어려움을 가진다.
단순히 인터페이스를 분리하여 개별적으로 구현하는것은 코드 중복과 유지보수에 불편함을 가진다.
전략패턴을 사용한다면 행동을 외부로 위임하여 코드 중복 문제를 해결하고, 때에따라 유연하게 행동을 변경할 수 있다.