[JAVA] 61. 디자인 패턴 - 전략 패턴

윤설안's avatar
Jul 21, 2025
[JAVA] 61. 디자인 패턴 - 전략 패턴
💡

SOLID 원칙

약어
원칙 이름
한글 뜻
핵심 개념
S
Single Responsibility Principle
단일 책임 원칙
클래스는 하나의 책임만 가져야 한다
O
Open/Closed Principle
개방-폐쇄 원칙
확장에는 열려 있고, 변경에는 닫혀 있어야 한다
L
Liskov Substitution Principle
리스코프 치환 원칙
자식 클래스는 부모 클래스를 대체할 수 있어야 한다
I
Interface Segregation Principle
인터페이스 분리 원칙
클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안 된다
D
Dependency Inversion Principle
의존 역전 원칙
추상화에 의존하고, 구체적인 것에 의존하지 말아야 한다

전략 패턴이란?

객체가 수행할 수 있는 각각의 행위를 별도의 전략 클래스로 만들고, 이 전략들을 캡슐화한 인터페이스를 정의하여 객체의 행위를 동적으로 바꾸고 싶을 때, 직접 코드를 수정하지 않고 전략만 교체함으로써 행위를 유연하게 확장하는 설계 패턴입니다.
쉽게 말해, 객체의 여러 행동을 전략(클래스)으로 분리해두고, 필요할 때 그 전략을 교체하여 행동을 바꾸는 방식입니다.

전략 패턴을 사용하지 않는 예시

public class App { public static void main(String[] args) { Mouse m1 = new Mouse(); Doorman d1 = new Doorman(); d1.쫓아내(m1); }
public class Mouse { private String name = "쥐"; public String getName() { return name; } }
public class Doorman { public void 쫓아내(Mouse mouse) { System.out.println(mouse.getName() + " 나가"); } }
현재 코드는 DoormanMouse만 쫓아낼 수 있습니다. 이 상태에서는 문제가 없지만, 만약 다른 동물도 쫓아내야 한다면 어떻게 될까요?

예를 들어, Tiger 클래스를 추가해보겠습니다.
public class Tiger { private String name = "호랑이"; public String getName() { return name; } }
Tiger를 쫓아내기 위해서는 Doorman을 다음과 같이 수정해야 합니다.
public class App { public static void main(String[] args) { Mouse m1 = new Mouse(); Doorman d1 = new Doorman(); d1.쫓아내(m1); Tiger t1 = new Tiger(); d1.쫓아내(t1); } }
public class Doorman { public void 쫓아내(Mouse mouse) { System.out.println(mouse.getName() + " 나가"); } public void 쫓아내(Tiger tiger) { System.out.println(tiger.getName() + " 나가"); } }

이렇게 Doorman 클래스를 수정(오버로딩)하면 당장은 동작하지만, SOLID 원칙 중 OCP(개방-폐쇄 원칙)에 위배됩니다.
OCP란?
"확장에는 열려 있고, 변경에는 닫혀 있어야 한다"
즉, 기능을 추가할 때 기존 코드를 수정하지 않아야 한다는 뜻입니다.
여기서는 Tiger가 추가될 때마다 Doorman 클래스를 계속 수정해야 하므로 OCP를 위반하게 됩니다.
이럴 경우에는 어떻게 해야하는가?

해결 방법: 추상화 도입

MouseTiger 모두 동물이므로, 이들의 공통 부모 클래스나 인터페이스인 Animal을 만들어서 공통 기능을 추상화할 수 있습니다.
public abstract class Animal { public abstract String getName(); }
package ex01; public class Tiger extends Animal { private String name = "호랑이"; public String getName() { return name; } }
package ex01; public class Mouse extends Animal { private String name = "쥐"; public String getName() { return name; } }
그리고 Doorman 클래스는 다음과 같이 수정합니다.
public class Doorman { // 객체의 책임 public void 쫓아내(Animal a) { System.out.println(a.getName() + " 나가"); } }
이렇게 하면 Doorman은 구체적인 동물 클래스에 의존하지 않고 추상화된 Animal에만 의존하게 되어, 새로운 동물이 추가되어도 Doorman 코드를 수정하지 않아도 됩니다.

SOLID 원칙 준수 여부

  • OCP(개방-폐쇄 원칙):
    • 기존 코드를 수정하지 않고 새로운 동물 클래스를 추가할 수 있어 원칙에 부합합니다.
  • DIP(의존 역전 원칙):
    • Doorman이 구체적인 동물 클래스가 아닌 추상 Animal에 의존함으로써 원칙을 준수합니다.
 
Share article

An's Blog