객체 지향의 핵심 5가지 중 2가지를 배웠다.
1. 상태는 행위를 통해 변경한다.
2. DIP(의존성 역전의 원칙)
오늘은 5가지 중 3번째, SRP에 대해 알아보자.
SRP 단일 책임의 원칙 (Single Responsibility Principle)
객체는 객체들끼리 협력함 -> 프로그램이 만들어짐
= 부품이 결합되는 것처럼 프로그램 만들기 편함
협력의 관계는 DIP를 지켜야한다.
추상적인 것을 바라보고 협력해야 한다.
서로 메시지를 교환하며 협력한다.
메시지를 전달하는 행위를 메서드 호출이라고 한다.
어떤 특정 객체가 가지고 있는 메서드를 책임이라고 한다.
객체들 간의 협력, 메시지 교환, 책임이 객체 지향의 3요소이다.
프로그램 설계를 위해 srp를 배우는 것이 아닌,
srp로 설계된 코드를 보고 객체의 책임을 볼 줄 알기 위해 알아야 한다.
설계된 틀 안에 내부 코드를 우리가 짜기 위해서는 잘 파악할 줄 알아야 한다.
요리사인 홍길동, 종업원인 장보고가 있는 식당에 손님 임꺽정이 있다.
식당에서 각자의 책임이 무엇인지 생각해보자.
임꺽정은 주문을 해야 하는 책임이 있을까?
아니다. 주문을 하고 말고는 임꺽정의 마음이지 책임이 될 수 없다.
임꺽정은 음식을 먹을 책임이 있다.
장보고의 책임에는 계산하기, 서빙하기, 주문받기가 있다.
홍길동은 요리 만드는 책임이 있다.
이때 사람들의 이름이 바뀌면 일일이 수정해야 하니까
DIP를 지켜 추상화시켜준다.
임꺽정 -> 손님
장보고 -> 종업원
홍길동 -> 요리사
객체는 객체들끼리 메시지를 주고받으며 협력한다고 했다.
그런데 지금 종업원의 책임이 너무 많아졌다.
이럴 바에는 객체를 하나 더 생성하여
책임을 분산시키는 게 좋다.
예를 들면 종업원을 한 명 더 생성시키는 것처럼 말이다.
책임을 바탕으로 프로그램을 요리 프로그램을 만들어 볼 것이다.
1. srp이름의 패키지를 만들어준다.
2. 파일 5개를 생성한다.
요리사.java
종업원.java
손님.java
음식.java
요리프로그램.java (main 실행을 하는 파일)
3. 각자의 책임에 따라 프로그램 설계도를 만들었다.
손님과 종업원의 관계가 생기고, 종업원과 요리사의 관계가 생겼다.
위 설계도에 따라 코드를 짜 보도록 하자.
main에서 손님과 종업원, 요리사를 new 해준다.
이때 중요한 것이 있다.
이 프로그램에서 시작하는 사람은 누구일까?
손님이 주문을 하면서 시작하게 될 것이다.
하지만 손님을 호출할 수 있는 메서드가 없다.
손님이 가진 책임이 없기 때문이다.
아무나 프로그램을 시작할 수도 없고,
손님이 주문하면서 프로그램이 시작된다.
이 프로그램에 필요한 책임은 아니지만,
누군가는 메서드 호출을 시작해야 하므로
손님에게 주문하기( ) 메서드를 만들어 준다.
관계 형성은 메시지로 하는 것(메서드 호출)이므로
아무런 책임이 없을 수는 없는 것이다.
package srp;
public class 요리프로그램 {
public static void main(String[] args) { // main 실행
손님 customer = new 손님();
종업원 manager = new 종업원();
요리사 chef = new 요리사();
// 이 요리 프로그램의 딱한가지 문제점
// 손님이 관계하지 않는 요리사의 주소를 매개변수로 갖고가는거
// 종업원이 요리사의 주소를 알 수 없기때문에
customer.주문하기(manager, chef);
}
}
main에서 손님의 주문하기( ) 메서드를 호출하면서 프로그램이 시작된다.
그런데 주문하기( ) 메서드에 인수가 2개 들어있다.
왜 2개인지 뒤에서 알게 된다.
package srp;
// 손님 - 종업원 (의존성(관계))
// 손님이 종업원을 호출하니까 종업원의 레퍼런스 주소값을 알아야함.
public class 손님 {
// 주문받기가 끝나야 주문하기가 끝나기 때문에 뒤에들어온게 먼저나가는
// 스택 !, 책을 쌓아두는 구조, 햄버거게임
public void 주문하기 (종업원 manager, 요리사 chef) { // 시작점 메서드
// 종업원이 떠있는 heap 주소를 알아야 관계를 가질 수 있음.
음식 jjajang = manager.주문받기(chef);
System.out.println(jjajang.getName() + "을 먹습니다.");
}
}
손님은 종업원에게 주문을 해야 하는 관계가 있다.
의존적이라고도 말한다.
손님이 종업원을 호출하니까 종업원의 heap 주소 값을 알아야 한다.
그래야 종업원과 관계를 가질 수 있기 때문이다.
그런데 손님 클래스에서 종업원의 heap 주소 값을 알 방법이 없다.
그래서 많이 하는 실수가 손님의 클래스에서
종업원을 new 하여 새로운 메모리 공간에 띄우는 것이다.
손님에게는 종업원을 new 할 책임이 없다.
우리가 배운 내용 선에서는 주문하기( ) 메서드를 호출할 때 매개변수로
종업원의 주소 값이 저장된 변수를 받아오는 방법밖에 없다.
그래서 main에서 주문하기( ) 메서드를 호출할 때 종업원의 정보를 인수로 넘겨주었던 것이다.
이제 손님이 종업원에게 주문받기( ) 메서드를 호출할 것이다.
package srp;
// 종업원 - 요리사(의존성)
public class 종업원 {
// 요리사에게 의존적이기 때문에 매개변수로 레퍼런스 주소를 전달받음
public 음식 주문받기(요리사 chef) {
// 종업원이 음식생성의 책임은 없으니 new 하면안됨!
음식 jjajang = chef.음식생성();
// return값에 일단 뭔가 넣어줘야하는데 뭘 넣어야할지 모를때
// null 아무것도 없음, 빈 객체를 리턴
// 값이 없다는 것 자체도 데이터
return jjajang;
}
}
종업원 또한 요리사에게 의존적인 관계이다.
종업원이 요리사의 음식 생성( ) 메서드를 호출하기 위해서는 또한
요리사의 heap공간 주소 값을 알아야 한다.
이 주소 값 또한 알아올 방법이 없어서
처음에 main에서 손님을 호출할 때 종업원의 주소 값, 요리사의 주소값
2개를 넘겨준 것이었다.
종업원은 손님에게서 받은 요리사의 주소 값으로
음식 생성( ) 메서드를 호출해준다.
package srp;
public class 요리사 {
// 요리사는 누구에게도 의존적이지 않으니까 받아올 매개변수가 없다.
public 음식 음식생성() {
음식 jjajang = new 음식("짜장면");
return jjajang;
}
}
요리사는 누구에게도 의존적인 관계가 없으므로
음식생성( ) 메서드를 호출할 때 아무런 매개변수가 필요 없었다.
음식 생성을 하면 요리사가 new 해서 음식을 만들어준다.
package srp;
// 설계도
public class 음식 {
private String name;
// 음식 이름을 초기화 하기 위한 생성자
public 음식(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
새로 new 되어 만들어진 음식은
음식 클래스에서 생성자가 음식의 상태를 초기화하여 리턴된다.
초기화된 음식을 요리사는 다시 종업원에게 넘겨주고,
종업원은 손님에게 전달하며
프로그램은 종료된다.
메서드를 호출하면서
계속 매개변수를 넘겨주어야 해서 의존관계가 생겼다.
이때 귀찮다고 매개변수를 만들지 않고
아무데서나 필요하다고 new하지 못하게
싱글톤 패턴으로 만들어야 한다.
싱글톤 패턴을 사용하지 않고는 어떻게 만들어야 할까?
우리가 짠 프로그램처럼
손님과 요리사는 아무런 관계가 없지만,
종업원이 요리사의 주소를 알기 위해서는
손님에게 요리사 주소를 넘기고 요리사 주소를
다시 종업원에게 넘겨서 전달해주어야 한다.
그게 이 프로그램의 유일한 문제점이다.
[출처]
https://cafe.naver.com/metacoding
메타코딩 : 네이버 카페
코린이들의 궁금증
cafe.naver.com
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9
메타코딩
문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com
www.youtube.com