Strategy Pattern

Muzi·2023년 5월 4일
0

디자인 패턴

목록 보기
7/14

Intro

전략(Strategy)란?

게임을 예시로 들면 게임 캐릭터마다 공격 방식을 다르게 하고싶을때(궁수는 활로, 전사는 검으로, 격투가는 주먹으로)

이때 캐릭터들은 어떤 무기로 어떤 방식을 사용하던간에 공격을 한다

  • 어떤 목적을 달성하기 위해 일을 수행하는 방식, 비즈니스 규칙, 문제를 해결하는 알고리즘

Stragey Pattern

정리가 너무 잘 되어있어요,,

즉, 전략 패턴은 객체들이 할 수 있는 행위들 각각을 전략으로 만들고, 객체의 행위를 바꾸고 싶을때 직접 수정하는게 아니라, 전략을 바꾸는 것만으로 행위의 수정이 가능하도록 만든 패턴

  • Strategy: 인터페이스나 추상 클래스로 외부에서 동일한 방식으로 알고리즘을 호출하는 방법을 명시
  • ConcreateStrategy1, 2, 3: 전략 패턴에서 명시한 알고리즘을 실제로 구현한 클래스
  • Context: 스트래티지 패턴을 이용하는 역할 수행. 필요에 따라 동적으로 구체적인 전략을 바꿀 수 있도록 setter 메서드 제공

Code with Java

Before

  • 기차와 버스라는 탈것이 있고 두 클래스는 Movable 인터페이스의 구현체

Movable

public interface Movable {
    public void move();
}

public class Train implements Movable{
    public void move(){
        System.out.println("선로 이동");
    }
}

public class Bus implements Movable{
    public void move(){
        System.out.println("도로 이동");
    }
}

client

public class Client {
    public static void main(String args[]){
        Movable train = new Train();
        Movable bus = new Bus();

        train.move(); // 기차는 선로로
        bus.move(); // 버스는 도로로
    }
}

코드의 문제점

기존 버스의 이동 방식을 수정하려면 어떻게 해야하는가?

새로운 탈것이 추가되고 이동 방식을 추가하거나 수정하려면 어떻게 하는가?

  • 버스가 도로중에서도 고속 도로로만 이동한다고 가정하자
public void move(){
    System.out.println("고속 도로 이동");
}

위 코드처럼 기존 Bus의 move()를 수정하면 될지 모른다

  1. 그러나 이러한 수정 방식은 SOLID의 원칙 중 OCP( Open-Closed Principle )을 위배한다
  • OCP에 따라 기존 코드의 변경없이 확장이 가능해야하는데 위 코드는 기존 move를 직접 수정해버렸다

  • 버스 말고도 택시, 오토바이, 비행기 등이 추가된다면? 선로를 이용한 오토바이, 고속도로를 이용하는 택시가 추가된다면?

  1. 기존 move()를 일일이 수정하는것 뿐 아니라, 같은 메서드를 여러 클래스에서 똑같이 정의하고 있으므로 메서드의 중복이 발생

After

무엇이 변화되는가에 중점을 가진다

  • 현재 탈것이 이동하는 load가 여러가지 방식을 가진다. 따라서, move에 대한 전략을 생성하자 ( RailLoadStrategy, LoadStrategy )

public interface MovableStrategy {
    public void move();
}

public class RailLoadStrategy implements MovableStrategy{
    public void move(){
        System.out.println("선로를 통해 이동");
    }
}

public class LoadStrategy implements MovableStrategy{
    public void move() {
        System.out.println("도로를 통해 이동");
    }
}
  • 탈것에 대해서도 정의를 다시하자

public class Moving {
    private MovableStrategy movableStrategy;

    public void move(){
        movableStrategy.move();
    }

	// 어떤 방식으로 이동할것인가?
    public void setMovableStrategy(MovableStrategy movableStrategy){
        this.movableStrategy = movableStrategy;
    }
}

public class Bus extends Moving{

}

public class Train extends Moving{

}
  • Client
public class Client {
    public static void main(String args[]){
        Moving train = new Train();
        Moving bus = new Bus();

        /*
            기존의 기차와 버스의 이동 방식
            1) 기차 - 선로
            2) 버스 - 도로
         */
        train.setMovableStrategy(new RailLoadStrategy());
        bus.setMovableStrategy(new LoadStrategy());

        train.move();
        bus.move();

        /*
            선로를 따라 움직이는 버스가 개발
         */
        bus.setMovableStrategy(new RailLoadStrategy());
        bus.move();
    }
}

장점

  • load의 구체적인 구현이 MovableStrategy에 의해 캡슐화
    • load가 추가되어도 변화에 대한 수용가능
  • ocp를 만족한다
    • 선로를 움직이는 버스처럼 새로운 기능이 추가되어도 기존 코드에 영향 x
  • 외부에서 load를 임의로 변경할수있다
    • setter를 통해 load를 외부에서 필요에 의해서 변경 가능하다

Reference

https://velog.io/@y_dragonrise/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4Strategy-Pattern
https://victorydntmd.tistory.com/292
https://hudi.blog/strategy-pattern/
https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-OCP-%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99

profile
좋아하는걸 열심히

0개의 댓글