커피숍의 로테이션을 생각해보자.
손님이 와서 메뉴판을 본다. 메뉴판을 보고 손님이 주문을 한다. 주문을 하면 바리스타가 주문을 받고, 커피를 생성한다
객체지향적으로 보면
손님은 주문을 할 의무가 있고,
메뉴판은 메뉴를 선택해야할 의무가 있고,
바리스타는 커피를 만들어야 할 의무가 있다.
전체적인 흐름을 보자.
public class CoffeeApp {
public static void main(String[] args) {
//메뉴 바리스타 손님
Consumer consumer=new Consumer();
Barista barista=new Barista();
MenuItem m1=new MenuItem("아메리카노",1500);
MenuItem m2=new MenuItem("카페라떼",2500);
MenuItem m3=new MenuItem("카푸치노",4000);
ArrayList<MenuItem>menuItems=
new ArrayList<>();
menuItems.add(m1);
menuItems.add(m2);
menuItems.add(m3);
Menu menu=new Menu(menuItems);
consumer.주문("아메리카노",menu,barista);
}
}
여기의 내용은 메뉴판의 전반적인 내용과, 손님과 바리스타를 만들고 마지막 줄에서 손님의 책임을 시작하는 구문이다.
손님 파일로 가보자.
package coffeeshop;
//손님의 책임은 구문
public class Consumer {
public void 주문(String menuName, Menu menu,Barista barista) {
MenuItem menuItem=menu.메뉴선택(menuName);
if(menuItem==null) {
System.out.println(menuName+"은 우리 커피숍에 없습니다");
}else {
Coffee coffee=barista.커피생성(menuItem);
System.out.println("커피 나왔습니다.");
System.out.println(coffee.getName());
System.out.println(coffee.getPrice());
}
}
}
손님은 주문을 한다.
첫 줄은 메뉴판에게 "메뉴선택" 이라는 책임을 요구하는 문장이다.
메뉴를 보자.
import java.util.ArrayList;
import lombok.Data;
//책임 : 메뉴 선택
@Data
public class Menu {
//메뉴 아이템들(컬렉션)
private ArrayList<MenuItem> menuItems;
public Menu(ArrayList<MenuItem> menuItems) {
this.menuItems = menuItems;
}
public MenuItem 메뉴선택(String menuName) {
for (MenuItem menuItem : menuItems) {
if(menuItem.getName().equals(menuName)) {
return menuItem;
}
}
return null;
}
}
메뉴는 경우에 따라 늘어날수도 있다. 만일 이를 배열로 선언한다면 어떻게 될까? 너무 배열을 딱 맞게 만들 경우 이후 배열이 늘어날 때 수정할수 없고, 늘어날 것을 고려해서 크게 만든다면, 얼마나 크게 늘어날지도 알수 없는데다가 지나치게 크게 만들게 된다면 그 만큼의 메모리 손실이 생긴다.
따라서 컬렉션 중에서도 ArrayList라는 것을 이용해보자.
배열과 유사하지만 배열을 늘리는 수식만 입력해준다면 배열의 크기가 동적으로 늘어나는 배열이다.
배열 내부의 값을 리턴하는 값이 있어야 하므로, getter과 setter이 필요하다. 이것 역시 다른 파일로 생성하자.
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MenuItem {
private String name;
private int price;
}
따라서, 메뉴에 원래 있던 아이템이, 받은 메뉴이름과 일치한다면, 메뉴아이템의 이름을 리턴하게 되는 것이고, 그것을 바리스타의 커피 생성이 받아내는 것이다.
근데 손님이 주문한 메뉴가 카페에 없을 수도 있잖는가.
그러면 커피숍에 메뉴가 없다는 것을 경고하고 프로그램이 종료된다.
하지만 손님이 요구한 커피가 메뉴에 있다면?
바리스타가 가지고 있는 "커피 생성"이라는 책임을 요구한다.
package coffeeshop;
//책임 : 커피 제조
public class Barista {
public Coffee 커피생성(MenuItem menuItem) {
return new Coffee(menuItem);
}
}
따라서, 바리스타는 커피아이템이라는 객체를 리턴하게 되고, 리턴받은 객체는 Consumer 파일로 들어가 커피가 나오게 된다.