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() + " 나가");
}
}
현재 코드는
Doorman
이 Mouse
만 쫓아낼 수 있습니다. 이 상태에서는 문제가 없지만, 만약 다른 동물도 쫓아내야 한다면 어떻게 될까요?예를 들어,
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를 위반하게 됩니다.이럴 경우에는 어떻게 해야하는가?
해결 방법: 추상화 도입
Mouse
와 Tiger
모두 동물이므로, 이들의 공통 부모 클래스나 인터페이스인 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