객체지향프로그래밍(Object Oriented Programming)이란?
- 자바는 대표적인 객체지향 프로그램 언어임
- 실제세계를 객체하는 단위로 나누고 객체들간의 상호작용을 의미한다.
- 즉, 프로그램을 여러개의 독립된 단위인 객체들의 모임으로 파악하고자 하는 것이다.
클래스와 객체의 정의와 용도
- 클래스 : 객체를 정의해 놓은 것으로 객체를 생성하는데 사용된다. → 제품 설계도
- 객체 : 실제로 존재하는 사물 또는 개념으로 객체가 가지고 있는 기능과 속성에 따라 용도가 달라진다. → 제품
객체와 인스턴스
인스턴스화? 클래스 → 인스턴스(객체)
인스턴스 : 어떤 클래스로부터 만들어진 객체
객체의 구성요소
객체는 속성과 기능의 집합이다.
속성 (property) - 멤버변수, 특성, 필드 상태
기능(function) - 메서드, 함수, 행위
객체치향 프로그래밍 vs 절차지향 프로그래밍
- 절차지향 프로그래밍
- 실행하고자 하는 절차를 정하고, 순차적으로 프로그래밍하는 방식으로 빠르지만 비효율적이고 유지보수가 어렵다.
- 객체지향 프로그래밍
- 구현해야할 객체들 사이의 상호작용을 프로그래밍하는 방식으로 상속, 다형성, 추상화, 캡슐화를 통해 결합도를 낮추고 응집도를 높일 수 있으며 코드의 재사용성도 높일 수 있다.
객체지향 프로그래밍 SOLID 원칙
SRP (Single Responsibility) 단일 책임 원칙
- 단일 책임 원칙은 하나의 모듈은 한 가지 책임을 가져야 한다는 것으로, 이것이 모듈이 변경되는 이유가 한가지여야함을 의미한다. 여기서 변경의 이유가 한가지라는 것은 해당 모듈이 여러 대상 또는 랙터들에 대해 책임을 가졋거는 안되고, 오직 하나의 액터에 대해셔만 책임을 져야 한다는 것을 의미한다.
단순하게 말해서
한 클래스가 수행할때 있는 기능이 여러개이면 클래스 내부의 함수끼리 강한 결합이 밸상함 -> 유지보수 비효율적
OCP (Open-Closed) 개방-폐쇄 원칙
- 개방 폐쇄 원칙은 확장에는 열려있고 변경에는 닫혀있어야 한다는 것으로, 기존 코드를 수정하지 않아도 동작을 추가하거나 변경해 기능을 확장할 수 있다는 것이다.
LSP (Liskov Substitution) 리스코프 치환 원칙
- 하위 타입 객체는 상위 타입 객체에서 가능한 행위를 수행할 수 있어야함
-> 즉, 상위 타입 캑체를 하위 타입 객체로 지환해도 정상적으로 동작해야함
- 상속관계에서는 꼭 일반화 관계(Is-A) 가 성립해야 한다는 의미
- 상속관계가 아닌 클래스들을 상속관계로 설정하면, 이 원칙이 위배됨 (재사용 목적으로 사용하는 경우)
불만족
만족
ISP (Interface Segregation) 인터페이스 분리 원칙
-
클라이언트는 자신이 사용하는 메소드에만 의존해야 한다는 원칙
-
한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 않아야 함
-> 하나의 통상적인 인터페이스보다는 차라리 여러 개의 세부적인 인터페이스가 나음
-
인터페이스는 해당 인터페이스를 사용하는 클라이언트를 기준으로 잘게 분리되어야 함
결론적으로는 단일 책임 원칙(SRP)과 인터페이스 분할 원칙(ISP)은 같은 문제에 대한 두 가지 다른 해결책이라고 볼 수 있다.
하지만 특별한 경우가 아니라면 단일 책임 원칙을 적용하는 것이 더 좋은 해결책이라고 할 수 있다.
-
상위 클래스는 풍성할수록 좋다.
풍성할수록 하위 클래스에게 많은 기능을 확장시켜주는 것이고, 형변환, 코드 중복을 줄여줍니다.
-
인터페이스 내에 메소드는 최소한 일수록 좋다.
인터페이스는 하위 클래스에게 구현을 강제하도록 하는 역할입니다. 즉, 최소한의 기능만 제공하면서 하나의 역할에 집중하라는 뜻입니다.
DIP (Dependency Inversion) 의존 역전 원칙
- 의존 관계를 맺을 때, 변하기 쉬운 것(구체적인 것)보다는 변하기 어려운 것(추상적인 것)에 의존해야함
- 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 됨
- 저수준 모듈이 변경되어도 고수준 모듈은 변경이 필요없는 형태가 이상적
SRP 와 ISP 는 객체가 커지는 것을 막아준다. 객체가 단일 책임을 갖도록 하고 클라이언트마다 특화된 인터페이스를 구현하게 함으로써 한 기능의 변경이 다른 곳까지 미치는 영향을 최소화하고, 이는 기능 추가 및 변경에 용이하도록 만들어 준다.
LSP 와 DIP 는 OCP 를 서포트한다. OCP 는 자주 변화되는 부분을 추상화하고 다형성을 이용함으로써 기능 확장에는 용이하되 기존 코드의 변화에는 보수적이도록 만들어 준다. 여기서 '변화되는 부분을 추상화'할 수 있도록 도와주는 원칙이 DIP 이고, 다형성 구현을 도와주는 원칙이 LSP 인 것이다.
출처
https://velog.io/@haero_kim/SOLID-%EC%9B%90%EC%B9%99-%EC%96%B4%EB%A0%B5%EC%A7%80-%EC%95%8A%EB%8B%A4#srp-single-responsibility-%EB%8B%A8%EC%9D%BC-%EC%B1%85%EC%9E%84-%EC%9B%90%EC%B9%99
https://mangkyu.tistory.com/m/194
https://devlog-wjdrbs96.tistory.com/m/380
https://github.com/backtony/Backend_Interview_for_Beginner/blob/master/Java.md
자바의 정석