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();
}
}
}