From d5950f089355304f40e6cac713921799cbd8a331 Mon Sep 17 00:00:00 2001 From: moondda <93575538+moondda@users.noreply.github.com> Date: Thu, 17 Nov 2022 20:57:44 +0900 Subject: [PATCH] Add files via upload --- ...353\223\234_4\354\243\274\354\260\250.txt" | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 "\355\201\264\353\246\260\354\275\224\353\223\234_4\354\243\274\354\260\250.txt" diff --git "a/\355\201\264\353\246\260\354\275\224\353\223\234_4\354\243\274\354\260\250.txt" "b/\355\201\264\353\246\260\354\275\224\353\223\234_4\354\243\274\354\260\250.txt" new file mode 100644 index 0000000..dc4e57f --- /dev/null +++ "b/\355\201\264\353\246\260\354\275\224\353\223\234_4\354\243\274\354\260\250.txt" @@ -0,0 +1,234 @@ +SOLID원칙(객체지향 5대 원칙) + +1. SRP 단일 책임 원칙 (Single Responsibility Principle) +- 단 하나의 책임(기능)만을 갖는다 +- 버그 발생 가능성을 낮춘다 + +=> 좋은 설계 -> 분리된 클래스(함수). +=> 높은 응집도 + 낮은 결합도 + +연산을 하는 함수가 있다,,만약 알람기능을 추가하고 싶다면,,? +함수(Calculator) ++add() ++subtraction() ++multiply() ++division() ++alarm() (x) + +또다른 함수(Alarm)을 만든다. + + + +"나는 A이자, B이자, C입니다" +=> "나는 A" + "나는 B" + "나는 C" + + +2. OCP 개방 폐쇄 원칙 (Open-Closed Principle) +- 기존에선 닫혀있고, 추가/확장에서 열려있다 + +=> 변경에 초점을 맞추자 +=> 자주 변하면,쉽게 변경할 수 있게 자주 변경되지 않으면 수정에 영향이 없게 + +ex) 더 많은 기능을 부여하고 싶다 +-> 기존 코드를 바꿔서 기능을 부여한다(x) +-> 기존은 냅두고, 새로운 함수를 추가한다(O) + +=> 캡슐화 - 인터페이스에 공통으로 쓰이는 기능을 정의한다 + +public class Client { + public static void main(String args[]){ + Animal cat = new Cat(); + Animal dog = new Dog(); + + cat.crying(); + dog.crying(); + } +} + +어떤 동물이 추가되던, 인터페이스에 있는 crying() 기능을 쓸 수 있다. = 쉬운 확장이 가능하다. + + + +3. LSP 리스코프 치환 원칙 (Liskov Substitution Principle) +=> 자식이 할 수 있으면 부모도 할 수 있어야 한다 +=> 부모/자식간의 일관성 필요 +=> 과연 올바른 상속 관계인가? + +ex) + +부모는 아이스크림을 먹을 수 있다 + +자식은 팽이팽이를 먹을 수 있다(O) +자식은 호떡을 먹을 수 있다(X) + +open class Rectangle(open val width: Int, open val height: Int) { + + open fun getArea() = width * height +} + + +class Square( + override val width: Int, + override val height: Int) : Rectangle(width, height) { + + //super.getArea()를 사용하지 않고 정사각형에 맞게 로직을 수정했습니다. + //이렇게 하면 상위 타입(Rectangle)의 기능을 제대로 구현하지 못하게 됩니다. + override fun getArea(): Int { + //return super.getArea() + return width * width + } + + + + +abstract class Shape { + + abstract fun getArea(): Int +} + +class Rectangle(val width: Int, val height: Int): Shape() { + + override fun getArea() = width * height +} + + +class Square(val width: Int) : Shape() { + + override fun getArea() = width * width +} + +class DoWork { + + fun work() { + + val rectangle: Shape = Rectangle(5,4) + + if(isCheckedRectangle(rectangle)) { + println(rectangle.getArea()) + } else { + throw RuntimeException() + } + + + val square: Shape = Square(5) + + if(isCheckedShape(square)) { + println(square.getArea()) + } else { + throw RuntimeException() + } + } + + fun isCheckedRectangle(rectangle: Shape) = rectangle.getArea() == 20 + + fun isCheckedShape(square: Shape) = square.getArea() == 25 + + +4. ISP 인터페이스 분리 원칙 (Interface Segregation Principle) +=> 사용하지 않는 인터페이스는 구현하지 않는다. 영향을 받아서도 안된다. 즉, 의존하면 안된다. +=> 낭비+버그 유발 +=> 일반적 인터페이스(X) 여러개의 구체적 기능을 하는 개개별의 인터페이스(O) + +interface Calculator { + + fun add() + + fun subtract() + + fun multiply() + +class Calculator2019: Calculator { + + override fun add() { + println("2019 add()") + } + + override fun subtract() { + println("2019 subtract()") + } + + override fun multiply() { + println("2019 multiply()") + } + + +class Calculator2015: Calculator { + + override fun add() { + println("2015 add()") + } + + override fun subtract() { + println("2015 substract()") + } + + override fun multiply() { + println("...") + } + +interface Calculator { + + fun add() + + fun subtract() + +} + +interface CalculatorRecent { + + fun multiply() +} + +class Calculator2015: Calculator { + + override fun add() { + println("2015 add()") + } + + override fun subtract() { + println("2015 substract()") + } + +} + +class Calculator2019: Calculator, CalculatorRecent { + + override fun add() { + println("2019 add()") + } + + override fun subtract() { + println("2019 subtract()") + } + + override fun multiply() { + println("2019 multiply()") + } + + + +5. DIP 의존 역전 원칙 (Dependent Inversion Principle) +=> 변화하기 "어려운" 것에 의존한다 +=> 변화하기 어려운것? -> 추상 클래스, 인터페이스 + +=> 변화에 유연한 설계가 가능해진다 + +추상 ->의존 구체(O) +구체 ->의존 추상(x) + +고수준 모듈 (또는 클래스): 도구와 함께 동작하는 클래스. +저수준 모듈 (또는 클래스): 수행하기 위한 도구. +추상: 두 클래스를 연결하는 인터페이스 +구체: 도구가 동작하는 방법 + +"클래스 + 도구" 보다 좋은 방법은 "클래스 + 인터페이스 + 도구" +클래스와 인터페이스는 도구가 어떻게 동작하는지 알 수 없어야 한다. + +=> 인터페이스(추상)을 통하여 고수준 모듈이 저수준 모듈에 대한 의존성을 줄인다. + +그림 : +https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898 + + + +