• 기능을 인터페이스로 추상화하고 여러 알고리즘으로 상호 교환 가능하게 하는 패턴

image

  • Strategy : 기능을 추상화 하는 인터페이스
  • Concrete Strategy : 알고리즘을 실제로 구현하는 클래스
  • Context : 전략을 호출하는 역할, 변하지 않는 템플릿 역할을 함

구현

  • Strategy
public interface Movable {
    public void move();
}
  • Concrete Strategy
public class Train implements Movable {
    @Override
    public void move(){
        System.out.println("Rail");
    }
}

public class Bus implements Movable {
    @Override
    public void move(){
        System.out.println("Road");
    }
}
  • Context : 변하지 않는 템플릿 역할을 함
    • 생성자나 setter로 Concrete 전략을 선택한다
public class Context {
    private Movable strategy;

    public Context(Movable strategy) {
        this.strategy = strategy;
    }

    public void move() {
        strategy.move();    // 위임
    }
}
  • Client(Main 메서드)
public class Main {
    public static void main(String args[]){
        Train train = new Train();
        Context context1 = new Context(train);
        context1.move();     // Rail

        Bus bus = new Bus();
        Context context2 = new Context(bus);
        context2.move();     // Road
    }
}

익명 내부클래스 사용

  • 클래스가 계속 늘어나는 것을 막기 위해 익명 내부클래스를 사용할 수도 있다
public class Main {
    public static void main(String args[]){
        // 익명 내부클래스 사용
        Movable vehicle = new Movable() {
            @Override
            public void move() {
                System.out.println("탈것이 움직입니다.");
            }
        };

        Context context1 = new Context(vehicle);
        context1.move();

        // 람다 사용
        Context context2 = new Context(() -> System.out.println("탈것이 움직입니다."));
        context2.move();
    }
}

파라미터 방식 (템플릿 콜백 패턴)

  • 기본에는 필드에 Strategy를 저장하는 방식이였다 (선조립 후실행)
  • 파라미터를 사용해서 실행시점에 전략을 유연하게 선택할 수도 있다
  • 단점 : 실행할 때 마다 전략을 계속 만들어야 한다
public class Context {
    public void move(Movable strategy) {    // 파라미터로 전략을 받음
        strategy.move();
    }
}

public class Main {
    public static void main(String args[]){
        // 람다 사용
        Context context = new Context();
        context.move(() -> System.out.println("탈것이 움직입니다."));
    }
}
  • 템플릿 콜백 패턴 (명칭변경)
    • Context -> Template
    • Strategy -> Callback
public interface Callback {
    public void move();
}

public class VehicleTemplate {
    public void move(Callback callback) {
        callback.move();
    }
}

public class Main {
    public static void main(String args[]){
        // 람다 사용
        VehicleTemplate template = new VehicleTemplate();
        template.move(() -> System.out.println("탈것이 움직입니다."));
    }
}

장점

  1. 새로운 전략이 추가되어도 기존 코드를 수정할 필요가 업다
  2. 런타임에서도 전략을 변경할 수 있다

단점

  1. 복잡도가 증가한다
  2. 클라이언트가 구체적인 전략을 알아야 한다