저번 면접에서 객체 모델링에 관해서 질문받았는데,
긴장 + 빨리 대답해야한다는 조급한 마음에 대답을 잘 못했습니다.
프로젝트 할 때 DB를 짜면서 한참을 팀원들과 고민했던 내용이었는데
면접 당시에는 머리가 초기화된것처럼 하나도 생각이 안나서 당황스러웠습니다..ㅠㅡㅠ
그래서 면접이 끝나고 천천히 다시 한번 정리해 봤는데
사실 정리하면서도 과연 이게 최선일까, 조금 더 나은 방법이 있지 않을까 자꾸 고민이 들어서
개발자 친구에게 물어봤더니, 이 책을 추천해 주었습니다.
공부해보고 조만간 리뷰 남기겠습니다. :)
https://book.naver.com/bookdb/book_detail.nhn?bid=7467601
관련 글은 총 3개로 나눠서 작성 할 예정입니다.
(1) 단순 모델링 - 인터페이스, 클래스 구현
(2) 디자인 패턴 적용 - 술이 들어가지 않은 칵테일(non-alcohol 칵테일)이 만들어 져야 할 때는?
즉, 객체의 변화가 필요할 때에는? - 데코레이터, 스트래티지 패턴
(3) 데코레이터와 스트래티지 패턴을 개선하면? - 커맨드 패턴
이번 포스팅은 (1)에 관련된 내용입니다.
Q.
칵테일은 여러 술들로 이루어져 있을 수 있지만, 그 재료가 되는 술이 칵테일 자체가 될 수도 있습니다.
술은 칵테일의 재료로 쓰일 수도 있지만, 칵테일 자체가 될 수도 있는 것이죠.
이 때 객체 모델링을 어떻게 하면 좋을까요?
A.아쉬운 답변 - 이렇게 하면 안됩니다..ㅠㅠ
일단, 면접에서는
술, 칵테일 class가 각각 있고,
술이라는 class가 칵테일의 재료 list에 들어갑니다.
라고 설명했습니다.
그렇지만 이 방식은, 술이 재료이면서 동시에 칵테일인 경우를 제대로 표현하지 못합니다.
면접관님께서도 그 부분에 대해서 말씀하셨는데,
그때는 그렇다면 재료 list의 size가 1이면, 술이자 칵테일인 것이므로
boolean형 변수를 하나 둬서 표현하겠다고 대답했습니다.
대답을 하면서도 현명하지 못한 대답이라는 생각이 들었고,
면접이 끝나고 나서 되돌아보면서는 엉망인 객체 모델링이라는 것을 깨달았습니다 ㅠㅠ
그래서 면접이 끝나고 며칠동안 어떻게 하면 조금 더 효율적일까에 대해 고민해 봤습니다.
A. 다시 생각해 본 답변
1. 정의
쉬운 설명을 위해
술은 "도수가 있는 음료"를 의미하고, 칵테일은 "단독으로 마실 수 있는 술"으로 정의하겠습니다.
즉, 술 안에는 단독으로 마실 수 있는 술과, 단독으로 마실 수 없는(오직 재료로만 쓰이는) 술이 있습니다.
이를 위해서 가장 기초가 되는 술이라는 인터페이스를 만들었습니다.
interface Alcohol {
public String whoami();
}
그리고, 술 인터페이스를 상속받은 칵테일이라는 인터페이스를 만들었습니다.
interface Cacktail extends Alcohol {
public String whoami();
public void getCacktailName();
}
그림으로 상속, 구현 관계를 그려보면 이렇게 됩니다
(대문자 i로 표시한 부분은 인터페이스 입니다.)
핑크색 클래스는 재료로만 쓰이는 술을 의미하고,
노란색 클래스는 칵테일을 의미합니다.
이때 칵테일은 여러 술이 혼합된 칵테일일 수도 있고, 재료로 쓰이면서 동시에 칵테일도 되는 술일 수도 있습니다.
2. 술은 칵테일의 재료가 될 수도 있고, 칵테일 자체가 될 수도 있습니다.
소주와 맥주는 단독으로 마실 수 있기에 칵테일이 됩니다.
그런데 소주와 맥주는 소맥이라는 칵테일의 재료로도 쓰일 수 있습니다.
즉, 소주와 맥주는 재료로 쓰이는 술인 동시에 칵테일이 됩니다.
그래서 소주는 핑크색 클래스(술 인터페이스를 구현한 클래스)가 아니라
노란색 클래스(칵테일 인터페이스를 구현한 클래스)가 됩니다.
// 소주
class soju implements Cacktail {
public String whoami() {
return "soju";
}
public void getCacktailName() {
System.out.println("This is Cacktail soju");
}
}
// 맥주
class macju implements Cacktail {
public String whoami() {
return "macju";
}
public void getCacktailName() {
System.out.println("This is Cacktail macju");
}
}
소맥은 소주 + 맥주로 만들어진 칵테일이기 때문에,
이 또한 노란색 클래스(칵테일 인터페이스를 구현한 클래스)가 됩니다.
// 소맥
class somac implements Cacktail {
private String material;
somac(Alcohol soju, Alcohol macju) {
this.material = soju.whoami() + "+" + macju.whoami();
}
public String whoami() {
return "Cacktail somac";
}
public void getCacktailName() {
System.out.println("This is Cacktail somac: " + this.material);
}
}
소주는 소주 자체가 칵테일이 될 수도 있고, 소맥이라는 다른 칵테일의 재료가 될 수도 있습니다.
그렇다면 소주는 칵테일로서도, 재료로서도 쓰일 수 있어야 합니다.
그림으로 표현하면 이렇게 됩니다.
즉, 소주와 맥주는 칵테일로서의 역할도 하고,
소맥의 재료로서의 역할도 합니다.
오늘의 포스팅은 여기까지입니다.
내용은 굉장히 적은 것 같은데, 그림과 코드를 넣으려니 시간이 꽤 많이 걸리네요..ㅎㅎ
다음 포스팅은 디자인 패턴으로 돌아오겠습니다!
다음 포스팅 예고) 지금 상태에서 non-alcohol 칵테일을 추가하고 싶을 때는?
읽어주셔서 감사합니다.
공감과 댓글은 큰 힘이 됩니다 :)
'programming > JAVA' 카테고리의 다른 글
자바의정석 14장. Optional 정리 (0) | 2022.02.24 |
---|---|
[Java] 면접을 위한 Java 개념 정리 1탄 (0) | 2020.11.01 |
[JAVA] 상속(Inheritance) 개념 정리 (0) | 2020.04.26 |
[JAVA] 다형성(Polymorphism) 개념 정리 (0) | 2020.04.26 |
[JAVA] 문자열 String 정리 (0) | 2020.04.11 |
댓글