본문 바로가기
학습/Java

SOLID 원칙

코동이 2021. 8. 1.

1. SRP(Single Responsibility Principle) 단일 책임 원칙


어떠한 클래스를 변경해야 하는  이유는 한가지 뿐이어야 한다

public class Unit {

private String name;
private int speed;

public void move() {
 if(name.equals("저글링") {
  speed += 3;
 } else if(name.equals("탱크") {
  if("탱크모드") {
   speed = 0;
  } else {
   speed= 10;
  }
 }
}
}

 

현재 클래스에서는 저글링과 탱크라는 2가지 객체에 대해서 검사 후 변경을 하고 있다. 따라서 SRP 원칙에 위배되며 다음과 같이 각각 객체에 대한 메서드로 분리한다.

 

class 저글링 extends Unit {
 public void move() {
  this.speed += 3;
 }
}

class 탱크 extends Unit {
 public void move() {
  if("탱크모드") {
   speed = 0;
  } else {
   speed = 10;
  }
 }
}

 

2. OCP(Open Closed Principle) 개방 폐쇄 원칙

확장에는 열려 있고 주변의 변화에 대해서는 닫혀있어야 한다.

상위 클래스 또는 인터페이스를 중간에 두고, 자신은 변화에 폐쇄적이지만
인터페이스는 외부의 변화에 대해 확장을 개방해줄 수 있다.

 

 Application은 내부로는 JDBC Interface를 통해 저장소가 접근이 가능하도록 폐쇄적으로 둔다. 외부로는 Oracle, MySQL, H2등의 다수의 저장소를 연결했으며 추가적으로 JDBC Interface에 새로운 저장소를 손쉽게 연결해 저장소를 추가하도록확장성을 열어둔다.  

 

3. LSP(Liskov Substitution Principle) 리스코프 치환 원칙

서브 타입은 언제나 자신의 기반(상위) 타입으로 교체 할 수 있어야 한다. 즉, LSP를 만족한다면 프로그램에서 부모 클래스의 인스턴스 대신 자식클래스의 인스턴스로 대체해도 정상적으로 작동된다.

 

대표적인 직사각형 - 정사각형 문제를 살펴보자. 기본적으로 정사각형은 직사각형이라고 할 수 있다. 왜냐하면 정사각형은 직사각형의 성질을 그대로 가지고 있기 때문이다. 따라서 직사각형을 상속받는 정사각형이라는 컨셉으로 상속구조를 만들어본다.

 

Rectangle.java

public class Rectangle {
    private int width;
    private int height;

    public void setWidth(final int width) {
        this.width = width;
    }

    public void setHeight(final int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
    
    public int getArea() {
        return width * height;
    }
}

 

Square.java

public class Square extends Rectangle {

    @Override
    public void setWidth(final int width) {
        super.setWidth(width);
        super.setHeight(width);
    }

    @Override
    public void setHeight(final int height) {
        super.setWidth(height);
        super.setHeight(height);
    }
}

Main.java

public void static mian(String[] args) {
 Rectangle rectangle1 = new Rectangle();
 rectangle1.setHeight(4);
 rectangle1.setWidth(5);
 rectangle1.getArea(); // 20
        
 Rectangle rectangle2 = new Square();
 rectangle2.setHeight(4);
 rectangle2.setWidth(5); 
 rectangle2.getArea(); // 25
}

직사각형의 넓이가 20, 정사각형의 넓이가 25로 결과가 상이하다. 논리적으로 "정사각형은 직사각형이지만 직사각형은 정사각형이 아니다" 라고 생각했지만 정사각형과 직사각형은 상속관계로 있을 수 없다.

 

4. ISP(Interface Segregation Principle) 인터페이스 분리 원칙

 

클라이언트는 자신이 사용하지 않는 메서드에 의존관계를 맺으면 안된다.

 지도라는 객체는 다양한 안내기능을 가지고 있다. 하지만, 자전거 네비게이션은 자동차, 하늘, 지하철 노선도는 필요하지 않다. 마찬가지로 다른 교통수단도 자신의 교통수단의 안내기능만 필요하다. 따라서 자신이 사용하는 메서드만 남기고 자신과 무관한 메서드는 모두 분리해야 한다.

 

5. DIP(Dependency Injection Principle) 의존원칙

 저수준 모듈이 고수준 모듈에 의존한다. 자신보다 변하기 쉬운 것에 의존해서는 안된다.

 

다음 그림은 사람과 옷의 관계로 고수준(사람)이 저수준(여름 옷, 봄 옷, 가을 옷)을 의존한다면 아래처럼 각각 수정을 하며 연쇄적으로 계절에 따라 다 변경해야 한다.

 

 하지만 고수준이 사람, 저수준 옷이므로 옷이라는 인터페이스를 통해 인터페이스를 역전한다. 사람은 옷이라는 정보만 가지고 있으며, 여름 옷, 봄 옷, 가을 옷은 상황에 따라서 교체해주도록 한다.

 

 

 

출처

https://medium.com/humanscape-tech/solid-%EB%B2%95%EC%B9%99-%E4%B8%AD-lid-fb9b89e383ef

반응형

'학습 > Java' 카테고리의 다른 글

GET과 Query Parameter, POST와 Databody  (0) 2021.08.03
REST, RESTful API  (0) 2021.08.01
POJO / Hibernate  (0) 2021.08.01
전략패턴이란?  (0) 2021.08.01
map vs flatMap  (0) 2021.05.16