728x90
반응형
SMALL

리스코프 치환 원칙

Liskov Substitution Principle, LSP

“서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다.” - 로버트 C. 마틴

'하위 클래스의 인스턴스는 상위형 객체 참조변수에 대입해 상위 클래스의 인스턴스 역할을 하는 데 문제가 없어야 한다'

리스코프 치환 원칙 - wiki

리스코프 치환 원칙을 위반한 계산기

원칙 위반 증상

객체의 타입을 확인합니다.(instanceof)자식 클래스명이 연관되거나 의존성이 있는 클래스에서 자주 발생합니다.

public class Calculator {
    // 연산 기능을 추상화된 부모클래스에 의존하여 처리한다.
    public int calculate(AbstractOperation operation, int firstNumber, int secondNumber) {
        // 나누기 연산 - 0처리 추가
        if(operation instanceof DivideOperation){
            if(secondNumber == 0){
                return -99999;
            }
        }
        return operation.operate(firstNumber, secondNumber);
    }
}
public class Client {
    public static void main(String[] args) {

        Calculator calculator = new Calculator();

        int firNum = 140;
        int secNum = 60;

        int answer = calculator.calculate(new AddOperation(), firNum, secNum);
        System.out.println(" + answer = " + answer);

        answer = calculator.calculate(new SubstractOperation(), firNum, secNum);
        System.out.println(" - answer = " + answer);

        answer = calculator.calculate(new MultiplyOperation(), firNum, secNum);
        System.out.println(" * answer = " + answer);

        answer = calculator.calculate(new DivideOperation(), firNum, secNum);
        System.out.println(" / answer = " + answer);
    }
}
public abstract class AbstractOperation {
    public abstract int operate(int firstNumber, int secondNumber);
}
public class AddOperation extends AbstractOperation {
    @Override
    public int operate(int firstNumber, int secondNumber) {
        return firstNumber + secondNumber;
    }
}
public class SubstractOperation extends AbstractOperation {
    @Override
    public int operate(int firstNumber, int secondNumber) {
        return firstNumber - secondNumber;
    }
}
public class MultiplyOperation extends AbstractOperation {
    @Override
    public int operate(int firstNumber, int secondNumber) {
        return firstNumber * secondNumber;
    }
}
public class DivideOperation extends AbstractOperation {
    @Override
    public int operate(int firstNumber, int secondNumber) {
        return firstNumber / secondNumber;
    }
}

추가적인 기능이 필요한 자식 클래스가 존재하기 때문에 타입 확인을 진행하고 있습니다.

따라서 자식 클래스의 인스턴스가 부모클래스의 인스턴스 역할을 수행하는데 문제가 없다고 할 수 없습니다.

원칙 적용 방법

부모 와 자식 클래스 사이의 행위가 일관성이 있도록 추상화를 좀 더 정교하게 구현합니다.

연산 기능을 추상화한 부모 클래스에 피연산자 값의 유효성 검사를 진행하는 메서드를 추가해 줍니다.

계산기 클래스에서는 이 메서드를 사용하여 유효성 검사를 진행하고 이 유효성 검사가 필요한 자식 클래스에서는 이 추가된 유효성 검사 조건을 구체화 합니다.

728x90
반응형
LIST

'개발 > JAVA' 카테고리의 다른 글

의존성 역전 원칙  (0) 2023.01.27
인터페이스 분리 원칙  (0) 2023.01.27
개방-폐쇄 원칙  (0) 2023.01.27
단일 책임 원칙  (0) 2023.01.27
SOLID  (0) 2023.01.27

+ Recent posts