FreeHand

SOLID 본문

Language/Java

SOLID

Jinn 2023. 11. 22. 01:36
SRP(Single Responsibility Principle, 단일 책임 원칙)

 

- What

객체는 하나의 책임만 가져야 한다.

여기서 책임이란 "할 수 있는 것" 또는 "해야 하는 것"을 의미한다.

SRP 적용 후

- Why

하나의 클래스가 너무 많은 책임을 수행한다면 변경에 유리한 코드를 작성하기 힘들다.

학생 클래스가 변경될 경우 학생 클래스의 역할을 필요로 하는 다른 코드 역시 변경해야 할 가능성이 높다.

 

- How

클래스들이 책임을 적절하게 분담하도록 변경한다.

학생 클래스가 모든 책임을 가질 때는 하나의 책임에 변경이 있어도 학생 클래스를 사용하는 다른 클래스들을 다시 테스트해야 한다. 하지만 학생 클래스의 책임을 여러 클래스가 분담하면 해당 책임을 갖는 클래스와 그 클래스를 사용하는 클래스만 영향을 받는다.

 

 

OCP(Open-Closed Principle, 개방-폐쇄 원칙)

 

- What

기존 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계해야 한다.

OCP 적용 전

- Why

Client가 성적표와 출석부를 출력하는 기능을 사용할 때 도서 대여 명부 같은 새로운 기록을 출력하는 기능을 사용하려면 도서 대여 명부 클래스를 만들어 Client가 사용할 수 있다. 하지만 이 방식은 새로운 기능을 추가하기 위해서 Client를 수정해야 하므로 OCP를 위반한다.

 

OCP 적용 후

- How

Client가 개별 클래스(성적표, 출석부, 도서대여명부)를 직접 처리하지 않고 인터페이스를 통해 사용하도록 한다.

이제 Client는 인터페이스를 사용하므로 변경될 일이 없고, 기능 추가를 위해서는 인터페이스의 구체 클래스만 새로 추가하면 된다.

 

 

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

 

- What

자식 클래스는 최소한 부모 클래스에서 가능한 행위는 수행할 수 있어야 한다. 즉, 부모 클래스와 자식 클래스 사이의 행위가 일관되어야함을 의미한다.

 

- Why

 

- How

 

 

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

 

- What

인터페이스를 클라이언트에 특화되도록 분리시켜야 한다는 원칙이다.

ISP 적용 전

- Why

각 클라이언트는 복합기 클래스에서 모든 기능을 다 사용하지 않는다. 따라서 사용하지 않는 기능에 의해 영향을 받는 일이 없도록 클라이언트에 특화된 인터페이스로 분리하는 것이다.

 

ISP 적용 후

- How

인터페이스를 통해 사용할 기능만 받도록 각 클라이언트에 적합한 인터페이스를 만든다.

 

 

DIP(Dependency Inversion Principle, 의존 역전 원칙)

 

- What

의존 관계를 맺을 때 자주 변하는 것보다 변화가 적은 것에 의존하라는 원칙이다.

즉, 구체적인 클래스보다 인터페이스나 추상 클래스에 의존하라는 의미이다.

 

- Why

자주 변하는 클래스를 의존하면 해당 클래스에 변경이 생겼을 때 의존 관계의 다른 클래스도 변경을 해야하므로 변경이 적은 인터페이스나 추상 클래스와 의존 관계를 맺어야 변경에 유연한 시스템이 된다.

 

DIP 적용 후

 

- How

OCP에서 봤던 클래스 다이어그램이다. 자주 변경될 수 있는 구체 클래스(성적표, 출석부 등)가 아닌 인터페이스에 의존하므로 구체 클래스가 변경되거나 추가되어도 Client 클래스는 변경할 필요가 없다.

public class Client {
    private Printable printable;
    
    public void setPrintable(Printable printable) {
        this.printable = printable;
    }
    
    public void print() {
        System.out.println(printabl.toString());
    }
}
public class ReportCard {
    public String toString() {
        return "Report card";
    }
}
public class Main {
    public static void main(String[] args) {
        Printable p = new ReportCard(); // 출석부, 도서대여명부로 교체
        Client c = new Client();
        c.setPrintable(p);
        c.print();
    }
}

DIP를 만족하면 DI(Dependency Injection, 의존성 주입)를 통해 변화에 유리한 코드를 작성할 수 있다.

의존성 주입이란 의존되는 대상인 외부 클래스의 객체를 인스턴스 변수에 주입하는 것을 말한다.

클라이언트가 성적표가 아닌 출석부를 뽑고 싶다면 new ReportCard()를 new AttendanceBook()으로 바꿔주기만 하면 된다.

'Language > Java' 카테고리의 다른 글

익명 클래스  (0) 2024.01.06
내부 클래스  (0) 2024.01.06
클래스 관계  (0) 2023.11.17
Generics  (0) 2023.08.01
[기타] 문자열 붙이기(repeat)  (0) 2023.07.12