전략(Strategy) 패턴이란?
전략 패턴이란 특정한 계열의 알고리즘들을 정의하고 각각을 캡슐화하여 사용할 수 있도록 만드는 패턴을 말합니다. 이를 활용하면 이 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있게 됩니다.
예제
다양한 오리를 등록해야하는 오리 시뮬레이션 게임의 오리 클래스 Duck을 예제로 예시를 적어보도록 하겠습니다.
Duck.java
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {}
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("모든 오리는 물에 뜹니다. 가짜 오리도 뜨죠");
}
}
Duck 클래스입니다. Duck 클래스는 추상클래스로 선언이 되어있으며 모든 오리는 생김새가 다르기 때문에 display()가 추상 메소드로 선언이 되어 있습니다. 그리고 모든 오리는 물에는 뜰 수 있을 것이기 때문에 swim()은 이 수퍼클래스에서 정의를 해주었습니다. 이제 오리마다 달라질 수 있는 나는 행동과, 울음 소리를 어떻게 해결하였는지가 이 전략 패턴 예제의 주 내용입니다.
일단 모든 나는 행동과, 울음 소리의 틀이 될 FlyBehavior, QuackBehavior 인터페이스를 각각 만들어 줍니다.
FlyBehavior.java
public interface FlyBehavior {
public void fly();
}
QuackBehavior.java
public interface QuackBehavior {
public void quack();
}
그리고 이 인터페이스들 가지고 새로운 나는 행동과, 울음 소리가 생길 때 마다 구현해줍니다. 예를 들면 아래와 같은 경우들이 존재할 수 있습니다.
FlyNoWay.java
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("저는 못 날아요.");
}
}
FlyWithWings.java
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("날고 있어요!");
}
}
MuteQuack.java
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("삑");
}
}
Quack.java
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("꽥");
}
}
장난감 오리는 날 수 없지만, 눌렀을 때 삑 소리를 낼 수 있습니다. 진짜 오리는 날개를 이용해 날 수도 있고, 꽥 하며 울음 소리를 낼 수도 있습니다. 이렇게 만들어 놓은 클래스들은 이제 각각의 오리들에게 맞는 행동을 끼워 맞춰주는 형식으로 사용할 수 있게 됩니다. 또 재사용도 가능하게 되었습니다.
MallardDuck.java
public class MallardDuck extends Duck {
public MallardDuck(){
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("청둥오리 입니다.");
}
}
ToyDuck.java
public class ToyDuck extends Duck{
public ToyDuck(){
flyBehavior = new FlyNoWay();
quackBehavior = new Squeak();
}
@Override
public void display() {
System.out.println("저는 장난감 오리입니다.");
}
}
위 처럼 청둥오리는 Quack()을 이용하여 꽉 소리를 내게 하며, FlyWithWings()를 이용하여 하늘을 날 수 있습니다. 또 장난감 오리는 Squeak()을 이용하여 삑 소리를 내게 하며, FlyNoWay()를 이용해서 날지 못함을 표현해 주었습니다.
위 코드들을 테스트 해보면 아래와 같은 실행 모습을 볼 수 있습니다.
MiniDuckSimulator.java
public class MiniDuckSimulator {
public static void main(String[] args){
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck toy = new ToyDuck();
toy.performQuack();
toy.performFly();
toy.setFlyBehavior(new FlyRocketPowered());
toy.performFly();
}
}
꽥
날고 있어요!
삑
저는 못 날아요.
로켓 추진으로 날아갑니다.