본문 바로가기

IT Book Summary/디자인패턴

Strategy pattern 스트래티지 패턴

 

스트래티지 패턴

- 알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있게 만든다

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

 

표준적인 객체지향 기법을 사용하여 Duck  수퍼클래스를 만든 후 확장해 여러종류의 오리를 만드는 경우

->Duck에 메소드 하나가 추가되면 Duck을 상속받은 모든 클래스에 같은 기능을 구현해 주어야 한다.

 

인터페이스를 활용하자.

 

서브클래스에서 Flyable, Quaackable 을 구현하도록 할 수 있다.

 

디자인 원칙
- 애플리케이션에서 달라지는 부분을 찾아내고, 달라지는 부분으로부터 분리 시킨다.
- 잘라지는 부분을 찾아서 나머지 코드에 영향을 주지 않도록 캡슐화 한다.
- 시스템의 유연성 향상.

 

바뀌는 부분과 그렇지 않은 부분 분리하기

- fly()와 quack()은 Duck 클래스에서 오리마다 달라지므로 각 행동을 나타낼 클래스 집합을 새로 만듬

 

 

오리의 행동 디자인

- Duck의 서브클래스에서는 인터페이스로 표현되는 행동을 사용.

- 구체적 행동은 Duck 서브클래스에 국한되지 않게 한다.

 

디자인 원칙
- 구현이 아닌 인터페이스/상위 형식에 맞춰 프로그래밍
Animal animal = new Dog();
animal.makeSound();

- 더 바람직한 방법은 구체적으로 구현된 객체를 실행시에 대입하는 것.
a = getAnimal();
a.makeSound();

 

Duck의 행동을 구현하는 방법

FlyBehavior와 QuackBehavior 두 인터페이스 사용하면

다른 형식의 객체에서도 나는 행동과 우는 행동을 재사용할 수 있고

또한 기존 행동클래스를 수정하거나 날아다니는 행동을 사용하는 Duck 클래스를 건드리지 않고 새로운 행동을 추가할 수 있다.

 

Duck 행동 통합하기

Duck에서 나는 행동과 소리를 내는 행동을 다른 클래스에 위임.

행동 인터페이스는 행동변수로 선언

 

public abstract class Duck {

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
...

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

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

}

 

 

인스턴스 변수 설정

MallardDuck 인스턴스가 만들어질때 생성자에 Duck 으로부터 상속받은 quackBehavior 인스턴스 변수에 Quack (구현클래스) 대입.

 

public class MallardDuck extends Duck {
    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlywithWings();
    }
    ...
}

 

동적으로 행동을 지정하기

Duck 클래스에 메소드를 새로 추가해 메소드를 호출하면 행동을 바꿀수 있게 한다.

 

public void setFlyBehavior (FlyBehavior fb) {
    flyBehavior = fb;
}

public void setQuackBehavior (QuackBehavior qb) {
    quackBehavior = qb;
}

 

캡슐화된 행동을 큰 그림으로 바라보자

 

각각 행동과 행동을 위임받는것. 

오리클래스에서는 행동을 상속받는 대신 올바른 행동 객체로 구성되어 행동을 부여받음.

디자인 원칙
- 상속보다는 구성을 활용한다
- "A는 B이다" 보다 "A에는 B가 있다"