PP: 절차적 프로그래밍
OOP : 객체지향 프로그래밍
Dog
라는 클래스가 존재하고, name
필드와 bark()
라는 메소드를 가지는 것이다.Account
라는 클래스가 있다고 가정하자.Account
에는 name
, number
, amount
등이 있을 것이다.withdraw()
, save()
등이 있을 것이다.Account
라는 클래스를 만들었고 이 것이 캡슐화이다.amount
를 아무나 접근 가능하다면? 문제가 발생할 것이다. amount
값만 바꿔주면 되기 때문이다.amount
를 private로 만들어주고 getter, setter나 다른 메소드 등을 통해서 접근하게 한다면 amount
를 실수로 수정하는 일이 없을 것이다. 이 또한 캡슐화이다.Account
의 save()
를 호출한다고 save()
의 내용을 알 수 있는가? 그것 또한 아니다. 이 것또한 캡슐화이다.save()
또는 find()
등을 통하여 데이터를 저장하고, 읽고, 업데이트하고, 삭제할 것이기 때문이다.Repository
라는 인터페이스를 만들고, LocalRepository
, MySQLRepository
, CSVRepository
와 같이 구현할 것이다.Repository
에 메소드를 정의하고 나머지 구현체들에서 오버라이딩할 것이다. 이 것이 추상화이다.Repository
라는 인터페이스를 만들었기 때문이다.add()
라는 함수가 있다고 가정하자.add(int num1, int num2)
, add(int num1, int num2, int num3)
가 존재하고 두 메소드 모두 인자로 전달된 수들을 더해서 반환한다.add()
인데 인자의 개수에 따라 두 수의 합, 세 수의 합으로 바뀌게 된다. 이 것이 다형성이다.ArrayList
는 List
를 구현한 AbstractList
를 상속한다. LinkedList
도 마찬가지이다.List
여도 다른 형태를 가질 수 있고 이 또한 다형성이다.List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new LinkedList<>();
TV
클래스가 존재한다. 이 TV는 현재 QHD 화질이다.TV
를 UHD로 업데이트 했다.TV
를 상속받아 QHDTV
를 만들고, 또 TV
를 상속받아 UHDTV
를 만든다. 그렇다면 QHD, UHD 모두 사용 가능하다.앞서 설명한 4가지가 OOP의 특징 이었다면, 이번엔 OOP의 원칙이다.
5대 원리들의 앞글자를 따와 SOLID라 부른다.
SRP(Single Reponsibility Principle)
Naver
라는 클래스가 존재한다고 가정하자.Naver
는 가지고 있는 책임이 너무나도 많다.NaverWebtoon
, NaverBlog
등으로.OCP(Open Close Principle)
Repository
를 다시 가져와 보자.Repository
로 추상화를 하지 않았다고 가정해보자.LocalRepository
만 존재 했다.LocalRepository
를 MySQLRepository
로 변경할 것이다.Repository
라는 인터페이스를 가지고 다양한 형태의 저장소를 확장시켜야 하는 것이다.LSV(The Liskov Substitution Principle)
ArrayList
와 LinkedList
를 가져와 보자.add(ArrayList list)
라는 메소드가 존재한다 이 메소드는 list
에 무언가를 추가한다. 그렇다면 이 메소드의 인자로 LinkedList
를 사용할 수 있는가?add(List list)
라는 메소드가 존재한다. 이 메소드는 둘 다 사용 가능한가?ISP(Interface Segregation Principle)
PhoneService
라는 인터페이스가 있다고 가정하자. PhoneService
에는 이 기능들이 모두 포함될 것이다. 현재로 DMB, 라디오 기능이 들어간 스마트폰도 존재하기 때문이다.DMBService
, RadiService
, MessageService
등과 같은 인터페이스로 불리시켜 하나의 책임을 가지게 만드는 것이 ISP 이다.DIP(Dependency Inversion Principle)
public class KakaoLogin {
String login() {
return "Kakao";
}
}
public class SocialLoginService {
private KakaoLogin login;
public void setLogin(KakaoLogin login) {
this.login = login;
}
public void login() {
return login.login();
}
}
SocialLoginService
또한 변경해야 할 것이다.public class KakaoLogin implements Login{
String login() {
return "Kakao";
}
}
public class NaverLogin implements Login{
String login() {
return "Naver";
}
}
public class SocialLoginService {
private Login login;
public void setLogin(Login login) {
this.login = login;
}
public void login() {
return login.login();
}
}
SocialLoginService
의 login
필드만 setter를 사용하여 원하는 소셜 로그인을 넣어주면 된다.