TIL (Today I learned

SOLID 의 LID

코딩준우 2024. 3. 11. 23:49

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

  • 타입 S가 타입 T의 서브타입이라면 기존 코드의 변경없이 타입 T의 객체를 타입 S의 객체로 교환(치환)할 수 있어야한다는 원칙이다.

Fish는 Cat의 서브타입이 아니므로 speak함수에 대한 재설계가 필요하다.

  • Cat 객체를 BlackCat으로는 치환할 수 있지만 Fish 객체로는 치환할 수 없다.
package solid;

public class LiskovSubstitutionPrinciple {
    static class Cat {
        public void speak() {
            System.out.println("meow");
        }
    }

    static class BlackCat extends Cat {
        @Override
        public void speak() {
            System.out.println("black meow");
        }
    }

    static class Fish extends Cat {
        @Override
        public void speak() {
            throw new IllegalArgumentException("Fish cannot speak");
        }
    }

    static void speak(Cat cat) {
        cat.speak();
    }

    public static void main(String[] args) {
        Cat cat = new BlackCat();
        speak(cat);

        cat = new Fish();
        cat.speak();
    }
}

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

  • 클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다.
  • 인터페이스 분리 원칙은 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 한다.



인터페이스 분리 원칙을 지키지 않은 코드

package solid;

public class InterfaceSegregationPrinciple {

    interface CarBoat {
        // 자동차 기능
        void drive();
        void turnLeft();
        void turnRight();

        // 보트 기능
        void steer();
        void steerLeft();
        void steerRight();
    }

    class Genesis implements CarBoat {
        @Override
        public void drive() {}

        @Override
        public void turnLeft() {}

        @Override
        public void turnRight() {}

        // 의미없는 매소드를 구현해야한다.
        @Override
        public void steer() {}

        @Override
        public void steerLeft() {}

        @Override
        public void steerRight() {}
    }
}

인터페이스 분리 원칙을 지킨 코드

package solid;

public class InterfaceSegregationPrinciple {

   interface Car{
        // 자동차 기능
        void drive();
        void turnLeft();
        void turnRight();
    }

    interface Boat{
        // 보트 기능
        void steer();
        void steerLeft();
        void steerRight();
    }

    static class Genesis implements Car{
        @Override
        public void drive() {}

        @Override
        public void turnLeft() {}

        @Override
        public void turnRight() {}
    }

    static class CarBoat implements Car, Boat{
        @Override
        public void drive() {}

        @Override
        public void turnLeft() {}

        @Override
        public void turnRight() {}

        @Override
        public void steer() {}

        @Override
        public void steerLeft() {}

        @Override
        public void steerRight() {}
    }
}



의존관계 역전 원칙 (Dependency Inversion Principle)


의존관계가 역전되지 않은 코드 (high level이 low level에 의존성이 있는 코드)

package solid;

public class DependencyInversionPrinciple {

    static class Cat {
        public void speak() {
            System.out.println("meow");
        }
    }

    static class Dog {
        public void speak() {
            System.out.println("bark");
        }
    }

    // 동물원은 고양이와 강아지에 대한 의존성이 존재함
    static class Zoo {
        private Cat cat;
        private Dog dog;
    }
}

양과 소에 대한 의존성 추가

package solid;

public class DependencyInversionPrinciple {

    static class Cat {
        public void speak() {
            System.out.println("meow");
        }
    }

    static class Dog {
        public void speak() {
            System.out.println("bark");
        }
    }

    static class Sheep {
        public void speak() {
            System.out.println("bark");
        }
    }

    static class Cow {
        public void speak() {
            System.out.println("bark");
        }
    }

    // 동물원은 고양이와 강아지에 대한 의존성이 존재함
    // 양과 소가 추가 된다면 양과 소에 대한 의존성도 생기게 됨
    static class Zoo {
        private Cat cat;
        private Dog dog;
        private Sheep sheep;
        private Cow cow;
    }
}

의존관계 역전을 통한 의존성 해결 코드

package solid;

import java.util.ArrayList;
import java.util.List;

public class DependencyInversionPrinciple {

    static class Animal {
        public void speak() {}
    }

    static class Cat extends Animal {
        @Override
        public void speak() {
            System.out.println("meow");
        }
    }

    static class Dog extends Animal {
        @Override
        public void speak() {
            System.out.println("bark");
        }
    }

    // 동물원은 고양이(Cat)와 강아지(Dog)에 의존성을 갖지 않고, 동물(Animal)에 대한 의존성만 가지게 됨
    static class Zoo {
        private List<Animal> animals = new ArrayList<>();

        public void addAnimal(Animal animal) {
            animals.add(animal);
        }

        public void speakAll() {
            for (Animal animal : animals) {
                animal.speak();
            }
        }

        public static void main(String[] args) {
            Zoo zoo = new Zoo();
            zoo.addAnimal(new Cat());
            zoo.addAnimal(new Dog());
            zoo.speakAll();
        }
    }
}