객체가 할 수 있는 유사한 행위들을 캡슐화하는 인터페이스를 정의하고, 각각의 행위에 대한 전략 클래스를 생성하여 객체의 행위를 동적으로 바꾸고 싶을 때 직접 행위를 수정하지 않고 전략을 바꿔주는 디자인 패턴.
전략을 사용하는 클라이언트와는 독립적으로 생성.
객체의 행위를 유연하게 확장하기 위한 디자인 패턴.
클라이언트는 시스템에 영향을 주지 않고 런타임에 사용되는 알고리즘을 변경 가능
move()
, temperature()
라는 2개의 행위가 가능하고 각각의 행위는 2종류의 기능이 가능 public abstract class Robot {
public abstract void move();
public abstract void temperature();
}
public class HotAndWalkingRobot extends Robot {
@Override
public void move() {
System.out.println("I'm walking now.");
}
@Override
public void temperature() {
System.out.println("It's hot.");
}
}
public class ColdAndWalkingRobot extends Robot {
@Override
public void move() {
System.out.println("I'm walking now.");
}
@Override
public void temperature() {
System.out.println("It's cold.");
}
}
public class HotAndRunningRobot extends Robot {
@Override
public void move() {
System.out.println("I'm running now.");
}
@Override
public void temperature() {
System.out.println("It's hot.");
}
}
public class ColdAndRunningRobot extends Robot {
@Override
public void move() {
System.out.println("I'm running now.");
}
@Override
public void temperature() {
System.out.println("It's cold.");
}
}
public class Main {
public static void main(String[] args) {
Robot robot = new HotAndWalkingRobot();
robot.move();
robot.temperature();
}
}
// 전략을 사용하는 클라이언트
public class Robot {
private MoveStrategy moveStrategy;
private TemperatureStrategy temperatureStrategy;
public Robot(MoveStrategy moveStrategy, TemperatureStrategy temperatureStrategy) {
this.moveStrategy = moveStrategy;
this.temperatureStrategy = temperatureStrategy;
}
public void move() {
moveStrategy.move();
}
public void temperature() {
temperatureStrategy.temperature();
}
}
// 유사한 행위를 하나의 인터페이스로 정의하고 각 행위를 클래스로 구현
public interface MoveStrategy {
void move();
}
public class Walk implements MoveStrategy {
@Override
public move() {
System.out.println("I'm walking now.");
}
}
public class Run implements MoveStrategy {
@Override
public move() {
System.out.println("I'm running now.");
}
}
public interface TemperatureStrategy {
void temperature();
}
public class Hot implements TemperatureStrategy {
@Override
public temperature() {
System.out.println("It's hot.");
}
}
public class Cold implements TemperatureStrategy {
@Override
public temperature() {
System.out.println("It's cold.");
}
}
// 사용할 전략을 객체 생성 시 전달
public class Main {
public static void main(String[] args) {
Robot robot = new Robot(new Walk(), new Cold());
robot.move();
robot.temperature();
}
}
리팩토링, 유지보수를 할 때마다 객체 지향의 특성을 살려서 추상화를 잘하고 구조를 잘 잡는게 얼마나 중요한 일인지 매번 깨닫습니다. 그런 의미에서 디자인 패턴은 시간날 때 하나씩 공부하고 각 패턴을 비교하면 도움이 많이 될 것 같아서 시리즈로 정리하려고 합니다.
전략 패턴은 이전에 NestJs로 개발을 할때 Passport.js를 사용하면서 공부했던 기억이 납니다. 정리를 하자면, 알고리즘 집합을 캡슐화하여 클라이언트와 결합도를 낮추고 런타임에 동적으로 전략을 선택할 수 있게 해주는 패턴입니다.
서비스마다 다르겠지만 저의 경우 생각보다 기획의 변경으로 로직이 변경되는 상황이 빈번했습니다. 그래서인지 전략 패턴의 핵심인 전략의 동적 선택을 알아보기 위해서 공부했었는데, 각 알고리즘을 캡슐화하여 유지보수를 쉽게 만들어주는 점이 더 인상 깊었던 것 같습니다 😄