SRP: 단일 책임 원칙 (Single Responsibility Principle)
OCP: 개방-폐쇄 원칙 (Open/Closed Principle)
LSP: 리스코프 치환 원칙 (Liskov Substitution Principle)
ISP: 인터페이스 분리 원칙 (Interface Segregation Principle)
DIP: 의존관계 역전 원칙 (Dependency Inversion Principle)
SRP 단일 책임 원칙 (Single Responsibility Principle)
- 한 클래스는 하나의 책임만 가져야 합니다.
- SRP에서 말하는 책임의 기본 단위: 객체
- 책임이란 객체가 수행하는 활동이라고 해석할 수 있습니다.
public class Professor {
public void teach(){}
public void load(){}
public void save(){}
public void printReport(){}
public void check(){}
}
위의 Professor 클래스는 여러개의 함수를 가지고 있습니다. 현재 Professor가 가장 잘할 수 있는 것은 가르치는 일입니다. 따라서 그 외의 다른 활동(책임)은 없애고 teach만 수행하도록 하는 것이 SRP를 만족하는 설계입니다.
OCP: 개방-폐쇄 원칙 (Open/Closed Principle)
- 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀 있어야 합니다. 즉 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계되어야 한다는 뜻입니다.
public class MyCar{
private Car car = new HyundaiCar();
//private Car car = new HyundaiCar();
private Car car = new KiaCar();
}
위의 코드처럼 처음에 현대자동차를 가지고 있다가 기아자동차를 가지게 되었을 때 코드의 변경이 발생하는 데 이럴 경우 구현 객체를 변경하려면 클라이언트 코드를 변경해야하고 다형성을 이용한 코드이긴 하지만 OCP설계원칙에 위반됩니다. 이럴 경우 Interface를 통해 표현해주는 것이 좋습니다.
LSP: 리스코프 치환 원칙 (Liskov Substitution Principle)
- MIT 컴퓨터 공학과 리스코프 교수가 1987년에 제안한 원칙입니다.
- LSP는 일반화 관계에 있어서 자식 클래스는 최소한 자신의 부모 클래스에 가능한 행위는 수행할 수 있어야 한다는 뜻입니다.
- LSP를 만족하면 부모클래스 대신에 자식 클래스의 인스턴스로 대체해도 프로그램의 의미가 변화하지 않습니다.
ex) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능인데 추가로 개발된 엑셀이 뒤로가게 된다면 LSP가 위반됩니다.
- 행위 일관성 pre -> pre', post' -> post
import java.util.*;
class MinMax {
public int[] mimax(int[] a) {
int[] b = a.clone();
Arrays.sort(a);
int minValue = a[0];
int maxValue = a[a.length-1];
b[0] = minValue;
b[b.length-1] = maxValue;
return b;
}
}
class MinMax1 extends MinMax {
public int[] mimax(int[] a) {
int[] b = a.clone();
Arrays.sort(a);
int minValue = a[0];
int maxValue = a[0];
b[0] = minValue;
b[b.length-1] = maxValue;
return b;
}
}
이런 식의 코드라면
public class MinMax2 extends MinMax{
public int[] mimax(int[] a) {
int[] b = a.clone();
Arrays.sort(b);
return b;
}
}
위의 코드가 적용된다면
ISP: 인터페이스 분리 원칙 (Interface Segregation Principle)
- Client should not be forced to depend upon interfaces that tey do not use
- 인터페이스를 클라이언트에 특화되도록 분리시키라는 설계 원칙입니다.
- 클라이언트의 관점에서 클라이언트 자신이 이용하지 않는 기능에는 영향을 받지 않아야 한다는 내용이 담겨있습니다.
- 분리하게 되면 인터페이스 자체가 변하더라도 클라이언트에 영향을 주지 않게 됩니다.
- 인터페이스가 명확해지고, 대체 가능성이 높아집니다.
ex) 비행기 인터페이스 -> 비행운전 인터페이스, 비행기정비 인터페이스
ex) 사용자 클라이언트 -> 운전자 인터페이스, 정비사 인터페이스,
DIP: 의존관계 역전 원칙 (Dependency Inversion Principle)
- DIP를 만족하려면 어떤 클래스가 도움을 받을 때 구체적인 클래스보다 인터페이스나 추상 클래스와 의존관계를 맺도록 설계해야 합니다.
class Person{
private Transportation transportation;
public void setTransportation(Transportation transportation) {
this.transportation = transportation;
}
public void board(){
System.out.println(transportation.toString());
}
}
abstract class Transportation{
abstract public String toString();
}
class Bus extends Transportation{
public String toString(){
return "Bus 탑승";
}
}
class Subway extends Transportation{
public String toString(){
return "Subway 탑승";
}
}
class Airplane extends Transportation{
public String toString(){
return "Airplane 탑승";
}
}
class Main{
public static void main(String[] args) {
Person p = new Person();
Transportation t = new Bus();
p.setTransportation(t);
p.board();
}
}
<참고문헌>
JAVA 객체지향 디자인 패턴 (UML과 GoF 디자인 패턴 핵심 10가지로 배우는) - 저자: 정인상, 채흥석
'CS' 카테고리의 다른 글
스트래티지 패턴 (Strategy Pattern) (0) | 2022.07.06 |
---|---|
객체지향 원리 (0) | 2022.06.24 |
객체지향 모델링 (0) | 2022.06.20 |
인터넷은 어떻게 작동되는 걸까? (0) | 2022.04.19 |
[Docker] Docker install tutorial build error - ERROR [build 2/2] RUN mkdocs build - Window (0) | 2022.04.09 |
댓글