본문 바로가기

Fundamental/Design Pattern

[디자인 패턴] 1. 전략 패턴(Strategy Pattern)

 

 

전략/정책 패턴(Strategy Pattern)
객체의 행위를 전략 또는 정책, 즉 상황에 따라 바꿔 끼워서 사용할 수 있도록 행위를 캡슐화하는 설계 패턴이다. 객체의 행위가 추후 변경되거나 추가될 가능성이 많을 때 효과적이다.

오리 시뮬레이션 게임, SimUduck

 

 

 

어느 한 게임 회사에서 오리를 시뮬레이션 하는 게임을 개발 중이었는데, 다른 게임 개발사와 차별화 시키기 위해서 기존 오리들 객체 행위에 날아다니는 행위를 추가하기로 결정했다.

 

 

 

MarllarDuck, RedheadDuck과 같은 모든 구상 클래스들에 fly()를 추가하는 건 효율적이지 않으니, 상속의 특징을 활용해서 부모 클래스인 Duck 클래스에 fly()를 추가하면, 아주 효율적으로 모든 오리 객체들이 날아다니는 행위를 할 수 있을 터였다.

 

 

 

하지만 문제가 생겼으니.. 날아다니면 안 되는 오리 객체들마저 날아다니게 된 것!

OOP에서 상속은 큰 장점이라고 생각했지만 유지보수 측면에선 오히려 단점이었던 것이다..

따라서 이번엔 quack() 행위와 같이 fly() 행위를 추상 메서드나 인터페이스로 만들어서 구상 클래스들이 구현하게 하면 될 듯 보였지만, 고민을 해보니 나중에 추가될 오리 객체들의 행위가 변화무쌍할 수 있겠다는 생각이 들었다.

 

그래서 이렇게 나중에 바뀌거나 추가될 행위들을 모두 캡슐화해서 독립적 특성을 가지도록 만들고, 추후 어떤 오리를 만들더라도 그 상황(전략, 정책)에 맞게 오리를 만들어낼 수 있도록 설계를 변경하게 된다...!

 

 

 

이제 상위 Duck 클래스를 수정하지 않고도 자유롭게 행위를 수정하거나 세부 행위를 추가할 수 있게 되었다.

 

// 행위 캡슐화
interface QuackBehavior {
    void quack();
}

class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("꽥");
    }
}

class Quuuk implements QuackBehavior {
    public void quack() {
        System.out.println("꾸욱");
    }
}

interface FlyBehavior {
    void fly();
}

class FlyWithWings implements FlyBehavior {
    public void fly() {
        System.out.println("날고 있어요~~");
    }
}

// 오리
abstract class Duck {
    QuackBehavior quackBehavior;
    FlyBehavior flyBehavior;

    public void Duck() {}

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

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

class MallarDuck extends Duck {
    public MallarDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }
}
public class Main {
    public static void main(String[] args) {
    	// 기본적으로 꽥꽥 거리고 날 수 있는 오리인 말라드 오리를 사용
        Duck mallard = new MallardDuck();
        mallard.performQuack();
        mallard.performFly();

        // 나중에 말라드 오리의 소리가 변경됐다면 행위 교체!
        mallard.quackBehavior = new Quuuk();
        mallard.performQuack();
    }
}

 


 

전략 패턴을 사용하면, 위 예시와 같이략, 정책(상황)에 따라 캡슐화된 행위를 조합해서 새로운 객체를 만들어낼 수 있고, 변경되더라도 다형성을 활용해서 부모 클래스를 수정하지 않고도 다른 클래스들에 영향을 주지 않으면서 독립적으로 행위를 변경할 수 있다.

 

 

전략 패턴에서 배울 수 있는 객체지향 원칙

  1. 바뀌는 부분은 캡슐화한다.
  2. 상속보다는 구성을 사용한다.
  3. 구현보다는 인터페이스에 맞춰서 프로그래밍한다.

 

전략/정책 패턴(Strategy Pattern)
객체의 행위를 전략 또는 정책, 즉 상황에 따라 바꿔 끼워서 사용할 수 있도록 행위를 캡슐화하는 설계 패턴이다. 객체의 행위가 추후 변경되거나 추가될 가능성이 많을 때 효과적이다.