KoreanFoodie's Study

디자인 패턴 (GOF) #3 - Liskov Substitution Principle (리스코프 치환 원칙) 본문

Game Dev/Design Patterns

디자인 패턴 (GOF) #3 - Liskov Substitution Principle (리스코프 치환 원칙)

GoldGiver 2022. 6. 7. 16:50

GoF 의 디자인 패턴강의를 참고하여 디자인 패턴에 대한 내용을 정리하고 있습니다.

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

리스코프 치환 원칙 (줄여서 LSP) 란, 기반 클래스가 있고 파생 클래스가 있을때, 기반 클래스가 들어가는 자리에 파생 클래스가 들어갈 수 있어야 하며, 이때 기반 클래스를 넣었을때의 의도대로 코드가 잘 동작해야 함을 의미한다. 

예를 들어, Rectangle 클래스를 기반 클래스로 한 Square 클래스를 보자. process 라는 함수에서 높이를 10으로 만든 후, 넓이를 반환하고 있다.

#include <iostream>

class Rectangle
{
protected:
    int width, height;
public:
    Rectangle(const int width, const int height)
        : width{ width }, height{ height } { }

    int get_width() const { return width; }
    virtual void set_width(const int width) { this->width = width; }
    int get_height() const { return height; }
    virtual void set_height(const int height) { this->height = height; }

    int area() const { return width * height; }
};

class Square : public Rectangle
{
public:
    Square(int size) : Rectangle(size, size) {}
    void set_width(const int width) override {
        this->width = height = width;
    }
    void set_height(const int height) override {
        this->height = width = height;
    }
};

struct RectangleFactory
{
    static Rectangle create_rectangle(int w, int h);
    static Rectangle create_square(int size);
};

void process(Rectangle& r)
{
    int w = r.get_width();
    r.set_height(10);

    std::cout << "expected area = " << (w * 10)
        << ", got " << r.area() << std::endl;
}

int main342342()
{
    Rectangle r{ 5,5 };
    process(r);

    Square s{ 5 };
    process(s);

    getchar();
    return 0;
}

위 코드를 실행하면 Rectangle 의 넓이는 의도대로 50이 나오지만, Square 의 경우 100 이 나오게 된다.

이는 LSP 를 위반한 것으로, 이를 해결하기 위해서는 RectangleFactory 등을 이용한 팩토리 메서드를 사용하는 방법 등을 활용하면 된다. (추후에 다룰 예정임)

 

Comments