💡자바 콘솔로 간단한 키오스크 만들기
메뉴 아이템 부분
public class MenuItem {
private String menuName;
private double menuPrice;
private String menuDescription;
메뉴 부분 (Category 및 MenuList 정의)
public class Menu {
private static Map<Integer, String> menuCategory = new HashMap<>() {{
put(1, "[ BURGERS MENU ]");
put(2, "[ DRINKS MENU ]");
put(3, "[ DESSERTS MENU ]");
}};
private static List<MenuItem> burgerMenuList = new ArrayList<>() {{
add(new MenuItem("ShackBurger ", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"));
add(new MenuItem("SmokeShack ", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"));
add(new MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"));
add(new MenuItem("Hamburger ", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거"));
}};
private static List<MenuItem> drinkMenuList = new ArrayList<>(){{
add(new MenuItem("Coke ", 6.9, "콜라"));
add(new MenuItem("Sprite ", 8.9, "사이다"));
add(new MenuItem("Fanta ", 6.9, "환타"));
add(new MenuItem("Beer ", 5.4, "맥주"));
}};
private static List<MenuItem> dessertMenuList = new ArrayList<>(){{
add(new MenuItem("Fries ", 6.9, "감자튀김"));
add(new MenuItem("Tender ", 8.9, "치킨텐더"));
add(new MenuItem("Coleslaw", 6.9, "코울슬로"));
add(new MenuItem("Egg Tart", 5.4, "에그타르트"));
}};
Kiosk 부분
static 전역변수로 정의Map으로 관리. <선택한 메뉴, 수량> 같은 메뉴 선택 시 수량 +1public class Kiosk {
static int inputNumber; // 입력값 받는 변수
static double totalPrice; // 총 금액
static Map<MenuItem, Integer> orderItemMap; //장바구니
입력값 및 에러 관리
enum 으로 정의된 값 활용하여 오타 발생 상황을 방지하였다private enum DefaultNumber {
ERROR(-1),
ZERO(0),
ONE(1),
TWO(2),
THREE(3),
FOUR(4),
FIVE(5);
private final int number;
DefaultNumber(int number){
this.number = number;
}
public int getValue(){
return number;
}
}
할인 정보
private enum DiscountType{
PATRIOT(1,"1. 국가유공자 : 10%", (num) -> num * 0.9),
SOLDIER(2,"2. 군인 : 5%", (num) -> num * 0.95),
STUDENT(3, "3. 학생 : 3%", (num) -> num * 0.97),
NORMAL(4,"4. 일반 : 0%", (num)-> num);
// 필드
private final int typeNumber;
private final String typeName;
private final Function<Double, Double> discountApply;
// 생성자
DiscountType(int typeNumber, String typeName, Function<Double, Double> discountApply) {
this.typeNumber = typeNumber;
this.typeName = typeName;
this.discountApply = discountApply;
}
// 연산 값 리턴
public double getDiscountedPrice(double num) {
return discountApply.apply(num);
}
public int getTypeNumber(){
return typeNumber;
}
}
입력 값 받는 메서드
Scanner 입력을 모두 하나의 메서드로 관리inputNumber = DefaultNumber(scanner, DefaultNumber.ZERO.getValue(), DefaultNumber.THREE.getValue());
//번호 입력받는 부분
private int DefaultNumber(Scanner scanner, int minNumber, int maxNumber){
try{
//스캐너 입력
inputNumber = scanner.nextInt();
scanner.nextLine();
//입력받은 숫자가 max 와 min 사이일 경우 리턴 -> 아닐경우 에러
if(inputNumber <= maxNumber && inputNumber >= minNumber){
return inputNumber;
}else {
System.out.println("숫자를 제대로 입력해 주세요. (" + minNumber +" ~ " + maxNumber + ")");
return DefaultNumber.ERROR.getValue();
}
//값이 이상할 경우 에러
} catch (Exception e) {
System.out.println("숫자를 제대로 입력해 주세요. (" + minNumber +" ~ " + maxNumber + ")");
scanner.nextLine();
return DefaultNumber.ERROR.getValue();
}
}
메뉴 선택 및 선택 메뉴 장바구니 추가
//메뉴 확인 후 선택
private MenuItem getSelectedMenuByNumber(List<MenuItem> menuList){
//입력받은 숫자에 해당하는 번호로 선택한 메뉴 정보 가져옴 (인덱스번호 == 선택한 번호 - 1)
MenuItem selectedMenu = menuList.get(inputNumber - DefaultNumber.ONE.getValue());
//메뉴 출력
System.out.println("선택한 메뉴 : " + menuList.get(inputNumber - DefaultNumber.ONE.getValue()).toString());
return selectedMenu;
}
//선택한 메뉴 장바구니에 넣기
private void addToOrderList(MenuItem selectedMenu) {
System.out.println("장바구니에 추가 : " + selectedMenu.getMenuName() + "\n");
//장바구니에 메뉴가 있을경우 수량 가져옴. 없을경우 0 가져옴
int quantity = orderItemMap.getOrDefault(selectedMenu, DefaultNumber.ZERO.getValue());
//메뉴가 있을경우 + 1, 없을경우 1.
orderItemMap.put(selectedMenu, quantity + DefaultNumber.ONE.getValue());
}
장바구니 총 금액 계산
Map 을 entrySet 로 변환한다.map 으로 key에서 가격 가져오고, value 에서 수량 가져와서 곱셈 연산을 해준다.reduce 함수로 연산한 결과 값 모두 더해준다.private double getTotalPrice(){
return orderItemMap.entrySet().stream()
.map(entry -> entry.getKey().getMenuPrice() * entry.getValue())
.reduce(0.0,(sum, now) -> sum + now);
}
할인 적용
Enum 에 정의된 할인 정보를 stream 으로 모두 출력Enum 에 정의된 할인 정보 중, 입력된 숫자에 대응되는 하나의 결과만 가져온 후, 정의되어 있는 값으로 연산 후 리턴.//할인정보 보여줌
private void showDiscountInfo(){
Arrays.stream(DiscountType.values())
.forEach(value -> System.out.println(value.typeName));
System.out.println();
}
//할인 정보 포함하여 계산 후 결과 값 리턴
private double getDiscountedPriceByNumber(){
//선택된 숫자로 enum 의 discountType 중 하나 선택 후 할인률 계산
return Arrays.stream(DiscountType.values())//enum 을 스트림으로 사용
.filter(value -> value.getTypeNumber() == inputNumber) //조건
.findAny()//하나의 값만 반환 -> 없으면 에러
.map(type -> type.getDiscountedPrice(totalPrice))
.orElse(totalPrice);// 계산 없을경우 기존 값 반화 -> 없으면 에러
}
[ MAIN MENU ]
1. Burgers
2. Drinks
3. Desserts
0. 종료 | 종료합니다.
1
[ BURGERS MENU ]
1. ShackBurger | W 6.9 | 토마토, 양상추, 쉑소스가 토핑된 치즈버거
2. SmokeShack | W 8.9 | 베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거
3. Cheeseburger | W 6.9 | 포테이토 번과 비프패티, 치즈가 토핑된 치즈버거
4. Hamburger | W 5.4 | 비프패티를 기반으로 야채가 들어간 기본버거
0. 뒤로가기
2
선택한 메뉴 : SmokeShack | W 8.9 | 베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거
위 메뉴를 장바구니에 추가하시겠습니까?
1. 확인 2. 취소
1
장바구니에 추가 : SmokeShack
[ MAIN MENU ]
1. Burgers
2. Drinks
3. Desserts
0. 종료 | 종료합니다.
[ ORDER MENU ]
4. Orders | 장바구니를 확인 후 주문합니다.
5. Cancel | 진행중인 주문을 취소합니다.
4
아래와 같이 주문 하시겠습니까?
[ Orders ]
SmokeShack | W 8.9 | 베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거 | 1개
ShackBurger | W 6.9 | 토마토, 양상추, 쉑소스가 토핑된 치즈버거 | 2개
Tender | W 8.9 | 치킨텐더 | 1개
Fanta | W 6.9 | 환타 | 1개
[ Total ]
W 38.5
1. 주문 2. 메뉴판
1
1. 국가유공자 : 10%
2. 군인 : 5%
3. 학생 : 3%
4. 일반 : 0%
1
주문이 완료되었습니다. 금액은 W 34.6 입니다.
문제점
Map의 Key 는 객체로 되어있는데, equals() 함수로는 중복된 값이 제대로 확인되지 않는다.원인
Object 의 비교에서는 equals() 와 == 가 동일하게 작동한다.해결
재정의(Override) 해야 논리적 비교가 제대로 작동한다.equal() 가 논리적으로 제대로 판별을 하며, Map, Set 에 중복되어 있는 값도 판별할 수 있다.@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
MenuItem menuItem = (MenuItem) o;
return Objects.equals(menuName, menuItem.menuName);
}
@Override
public int hashCode() {
return Objects.hashCode(menuName);
}
//변수
int inputNumber // 입력값 받는 변수
double totalPrice // 총 금액
int categoryNumber // 카테고리 번호
//메서드
private int getInputNumber // 입력값 받는 메서드
private MenuItem getSelectedMenuByNumber // 번호로 선택된 메뉴 리턴
private void addToOrderList // 장바구니에 객체 넣기
private double getDiscountedPriceByNumber // 금액 할인 적용 후 결과 리턴