[디자인 패턴] Strategy Pattern

Behavioral Pattern - Strategy Pattern

📚 의도

동일 계열의 알고리즘군을 정의하고, 각 알고리즘을 캡슐화하며, 이들을 상호교환이 가능하도록 만듭니다.
알고리즘을 사용하는 클라이언트와 상관없이 독립적으로 알고리즘을 다양하게 변경할 수 있게 합니다. (GoF)

사진사사진 찍기를 핸드폰으로 찍을 수 있고, 필름 카메라 혹은 폴라로이드 카메라로도 찍을 수 있다. 이처럼 여러 방식으로 가능한 일에 대해 모든 알고리즘을 각각의 클래스로 분리하고 이것을 전략이라고 부른다.

🧱 구조

  1. Context : strategy
    • 사진사
    • 전략들 중 하나를 담을 필드를 무조건 가지고 있어야 한다.
    • 이 전략이 무슨 전략인지 알 필요 없다. (Strategy interface)
  2. Client :
    • 원하는 전략을 생성해 Context에게 넘겨준다.
  3. Strategy :
    • 사진 찍기 interface
    • Context가 전략을 실행할 때 필요한 메소드를 선언한다.
  4. ConcreteStrategies :
    • Strategy를 다양한 알고리즘으로 구현하는 구현체.

💻 코드

  • 패턴 적용 전

    // 1. 기존 전략: 핸드폰 카메라
    public class Client {
        public static void main(String[] args) {
            takeMobilePhoto();
        }
    }
    
    // 2. 필름 카메라로도 찍고 싶다.
    public class Client {
        public static void main(String[] args) {
            int strategy = 2;
            takePhoto(strategy);
        }
    
        private static void takePhoto(int strategy) {
            if (strategy == 1) {
                takeMobilePhoto();
            } else if (strategy == 2) {
                takeFilmPhoto();
            }
        }
    
        private static void takeMobilePhoto() {
            System.out.println("핸드폰 카메라 촬영");
        }
    
        private static void takeFilmPhoto() {
            System.out.println("필름 카메라 촬영");
        }
    }
    
    // 3. 폴라로이드 카메라도 추가
    public class Client {
        public static void main(String[] args) {
            int strategy = 3;
            takePhoto(strategy);
        }
    
        private static void takePhoto(int strategy) {
            if (strategy == 1) {
                takeMobilePhoto();
            } else if (strategy == 2) {
                takeFilmPhoto();
            } else if (strategy == 3) {
                takePolaroidPhoto();
            }
        }
    
        private static void takeMobilePhoto() {
            System.out.println("핸드폰 카메라 촬영");
        }
    
        private static void takeFilmPhoto() {
            System.out.println("필름 카메라 촬영");
        }
    
        private static void takePolaroidPhoto() {
            System.out.println("폴라로이드 카메라 촬영");
        }
    }
  • 패턴 적용 후
  1. Context

    public class Photographer {
        PhotoBehavior photoBehavior;
    
        public Photographer(PhotoBehavior photoBehavior) {
            this.photoBehavior = photoBehavior;
        }
    
        public void performTakePhoto() {
            photoBehavior.takePhoto();
        }
    
        public void setPhotoBehavior(PhotoBehavior photoBehavior) {
            System.out.println("\n전략 변경\n");
            this.photoBehavior = photoBehavior;
        }
    }
  2. Client

    public class Client {
        public static void main(String[] args) {
            PhotoBehavior behavior = new MobilePhotoBehavior();
            Photographer photographer = new Photographer(behavior);
            photographer.performTakePhoto();
    
            behavior = new FilmCameraPhotoBehavior();
            photographer.setPhotoBehavior(behavior);
            photographer.performTakePhoto();
    
            behavior = new PolaroidPhotoBehavior();
            photographer.setPhotoBehavior(behavior);
            photographer.performTakePhoto();
        }
    }
  3. Strategy

    public interface PhotoBehavior {
        void takePhoto();
    }
  4. Concrete Strategies

    public class MobilePhotoBehavior implements PhotoBehavior {
        @Override
        public void takePhoto() {
            System.out.println("핸드폰 카메라로 촬영");
        }
    }
    public class FilmCameraPhotoBehavior implements PhotoBehavior {
        @Override
        public void takePhoto() {
            System.out.println("필름 카메라로 촬영");
        }
    }
    public class PolaroidPhotoBehavior implements PhotoBehavior {
        @Override
        public void takePhoto() {
            System.out.println("폴라로이드 카메라로 촬영");
        }
    }
  • Console

    // 출력
    핸드폰 카메라로 촬영
    
    전략 변경
    
    필름 카메라로 촬영
    
    전략 변경
    
    폴라로이드 카메라로 촬영

🔮 장단점

  • 장점
    1. 런타임시 알고리즘 변경 가능
    2. 핵심 코드와 구체적인 알고리즘을 분리할 수 있다.
    3. Open-Closed Principle: Context나 다른 Concrete Strategy의 변경 없이 새로운 전략 추가 가능
  • 단점
    1. 알고리즘이 몇 개 없다면 패턴을 적용하기에 과하다.

좋은 웹페이지 즐겨찾기