[디자인 패턴] 전략 패턴에 대한 나름의 이해

2023. 11. 18. 21:22디자인 패턴

전략 패턴의 정의는 다음과 같다.

The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

 

전략 패턴은 알고리즘의 계열을 정의하고 서로 바꿀 수 있게 한다.

예를 들어, duck 클래스를 다음과 같이 나타낼 수 있다.

package duck;

public abstract class DuckInheritance {

    public abstract void fly();

    public abstract void quack();

    public abstract void display();

    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
}

위와 같이 나타내면 모든 duck class를 상속받는 클래스는 fly와 quack을 구현해야 한다.

그런데 이 method는 상당 부분 중복될 여지가 있다. 가령, 날지 못하는 새들의 경우는 nofly라는 메소드를 사용한다.

이렇게 모든 클래스를 만들때마다 적으면 중복이 상당히 커져 유지보수가 힘들어진다.

 

이러한 문제를 해결하기 위해 fly와 quack을 다음과 같이 interface로 만든다.

package duck;

import duck.flybehavior.FlyBehavior;
import duck.quackbehavior.QuackBehavior;

public abstract class Duck {

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {

    }

    public abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

    public void peformQuack() {
        quackBehavior.quack();
    }

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }

    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }

}

위와 같이 만들면 새로운 duck을 만들때 마다 기존에 있는 FlyBehavior, QuackBehavior 인터페이스를 구현한 클래스를 가져와서 쓰기만 하면 된다. 즉, 날지 못하는 새는 NoFly라는 메소드를 가져와서 사용하기만 하면 되는 것이다. 

이 방법은 런타임에 어떤 behavior를 사용할지가 결정되기 때문에 유연한 코드를 가능하게 한다. 또한 위와 같이 setter를 사용하게 되면 flyBehavior를 NoFly에서 RocketFly로 유연하게 바꿀 수 있게 된다. 이렇듯 duck 클래스는 상속 관계인 is-a가 아닌 인터페이스를 가지는 has-a 관계를 가진다. has-a를 통해 클래스를 구성하는 방식을 조합이라고 한다. 예를 들어, duck 클래스는 FlyBehavior과 QuackBehavior를 '가진다'. car 클래스는 Tire와 Engine을 '가진다'. 구체적인 건 바꿔기워주기만 하면 된다. 고무 타이어를 철제 타이어로 바꾸기만 하면 된다. 

 

여기와 관련한 디자인 패턴 제3원칙은 다음과 같다.

상속보다 조합을 사용하자.

 

Reference


Freeman, E., Robson, E., Bates, B., & Sierra, K. (2021). Head First Design Patterns (2nd ed.). Canada: O’Reilly Media, Inc.