앞으로 디자인패턴에 대해 설명하기 앞서, SOLID 원칙을 먼저 살펴볼게요! (디자인패턴의 장점, 필요성 등을 설명할 때 꼭 필요한 원칙이라고 생각합니다)
시간이 지나도 유지보수와 확장이 쉬운 소프트웨어를 만드는데 사용되는 원칙
a.k.a. 객체지향 5대 원칙
SOLID는 각 원칙의 첫번째 글자를 따온거랍니다. 각 원칙에 대해 순서대로 설명하겠습니다 ㅎㅎ
어떤 클래스를 변경해야하는 이유는 오직 하나
변경해야하는 이유 == 책임입니다! 따라서, 1클래스 1책임이라는 원칙이죠.
만약 책임이 많아지면, 한 책임의 변화가 다른 책임에 영향을 주게됩니다.
이 원칙을 만족하면 불필요한 상속 및 구현을 줄여 가독성이 좋아지고 유지보수가 쉬워지며, 재사용성이 높아집니다.
기존의 코드를 변경하지 않고 기능을 수정하거나 추가할 수 있도록 설계
즉, 확장에 열려있고 변경에 닫혀 있는 설계를 해야한다는 원칙입니다.
이를 만족하지 않으면 새로운 기능을 추가하는 것이 어려워지는 변경의 유연함과 관련된 원칙입니다. 변하는 부분과 변하지 않는 부분을 구분해 설계하면 해당 원칙을 만족할 수 있습니다.
프로그램의 객체는 프로그램의 정확도를 깨트리지 않으면서 하위타입의 인스턴스로 바꿀 수 있어야 함
상위타입의 객체를 하위타입의 객체로 치환해도 상위타입을 사용하는 프로그램은 정상적으로 동작해야한다는 뜻입니다.
만약 이를 만족하지 않아 instanceOf(), 다운캐스팅을 이용해 정확한 타입을 확인해야하는 코드를 작성한다면 이는 OCP를 위배하게 됩니다. (subtype이 추가될때마다 instanceOf()등을 사용해 추가해야하니까!) 즉, 리스코프 치환법칙은 개방폐쇄원칙을 받쳐주는 다형성에 대한 원칙을 제공합니다! 🤓
클라이언트는 자신이 사용하지 않는 메소드에 의존 관계를 맺으면 안됨
클라이언트에서 Interface와 논리적으로 결합되어 필요한 메소드만 호출해 낮은 의존성을 가지라는거죠? 이 원칙은 단일책임원칙과 연관되어있는데요, ISP와 SRP은 객체가 커지지 않도록 막는 원칙입니다. 이를 통해 변경 시 영향을 최소화할 수 있습니다!
고수준모듈은 저수준모듈에 의존해서는 안되고 저수준모듈은 고수준모듈에서 정의한 추상타입에 의존
요구사항이 정해지면 상세수준(저수준모듈, 구체적인 클래스)의 변경이 발생할 가능성이 높아집니다. 하지만 상위수준(고수준모듈, 인터페이스 혹은 추상클래스)은 한 번 안정화되면 쉽게 변하지 않기 때문입니다! 이를 통해 abstraction에 대한 기반을 제공하죠. 따라서, LSP와 함께 OCP를 따르는 설계를 만들어주는 기반입니다!
+) OCP는 abstraction과 polymorphism으로 구현하는데, 각각은 DIP와 LSP이 기반이 됨