Strategy patterns(전략 패턴)
전략 패턴 ( Strategy Pattern )
객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여,
객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법을 말합니다.
간단히 말해서 객체가 할 수 있는 행위들 각각을 전략으로 만들어 놓고, 동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것만으로 행위의 수정이 가능하도록 만든 패턴입니다.
- 전략 패턴 사용 이유
기차( Train )와 버스( Bus ) 클래스가 있고, 이 두 클래스는 Movable 인터페이스를 구현했다고 가정하겠습니다.
그리고 Train과 Bus 객체를 사용하는 Client도 있습니다.
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("도로를 통해 이동");
}
}
public class Client {
public static void main(String args[]){
Movable train = new Train();
Movable bus = new Bus();
train.move();
bus.move();
}
}
기차는 선로를 따라 이동하고, 버스는 도로를 따라 이동합니다.
그러다 시간이 흘러 선로를 따라 움직이는 버스가 개발되었다고 가정해봅시다.
그러면 Bus의 move() 메서드를 다음과 같이 바꿔주기면 하면 끝납니다.
public void move(){
System.out.println("선로를 따라 이동");
}
그런데 이렇게 수정하는 방식은 SOLID의 원칙 중 OCP( Open-Closed Principle )에 위배됩니다.
OCP에 의하면 기존의 move()를 수정하지 않으면서 행위가 수정되어야 하지만, 지금은 Bus의 move() 메서드를 직접 수정했지요.
또한 지금과 같은 방식의 변경은 시스템이 확장이 되었을 때 유지보수를 어렵게 합니다.
예를 들어, 버스와 같이 도로를 따라 움직이는 택시, 자가용, 고속버스, 오토바이 등이 추가된다고 할 때, 모두 버스와 같이 move() 메서드를 사용합니다.
만약에 새로 개발된 선로를 따라 움직이는 버스와 같이, 선로를 따라 움직이는 택시, 자가용, 고속버스 ... 등이 생긴다면,
택시, 자가용, 고속버스의 move() 메서드를 일일이 수정해야 할 뿐더러, 같은 메서드를 여러 클래스에서 똑같이 정의하고 있으므로 메서드의 중복이 발생하고 있습니다.
즉, 지금과 같은 수정 방식의 문제점은 다음과 같습니다.
- OCP 위배
- 시스템이 커져서 확장이 될 경우 메서드의 중복문제 발생
따라서 이를 해결하고자 전략 패턴을 사용하려고 합니다.
개방 폐쇄 원칙 (Open-Closed Principle)의 정의
개방 폐쇄 원칙은 "확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다."를 의미합니다. 조금 더 쉽게 풀어 쓰자면, "기능을 변경하거나 확장할 수 있으면서 그 기능을 사용하는 코드는 수정하지 않는다."를 뜻합니다.
ts 로 표현시
interface MovableStrategy {
move();
}
class RailLoadStrategy implements MovableStrategy{
public move(){
console.log("선로를 통해 이동");
}
}
class LoadStrategy implements MovableStrategy{
public move() {
console.log("도로를 통해 이동");
}
}
class Moving {
private movableStrategy:MovableStrategy
public move(){
this.movableStrategy.move()
}
public setMovableStrategy( movableStrategy:MovableStrategy){
this.movableStrategy = movableStrategy;
}
}
class Bus extends Moving{
}
class Train extends Moving{
}
const bus = new Bus()
const train = new Train()
train.setMovableStrategy(new RailLoadStrategy());
bus.setMovableStrategy(new LoadStrategy());
train.move();
bus.move();
bus.setMovableStrategy(new RailLoadStrategy());
bus.move();
참고 페이지 https://victorydntmd.tistory.com/292?category=719467