요구사항
- ⬜ Enum을 활용한 사용자 유형별 할인율 관리하기
- ⬜ 사용자 유형의 Enum 정의 및 각 사용자 유형에 따른 할인율 적용
- ⬜ 예시 : 군인, 학생, 일반인
- ⬜ 주문 시, 사용자 유형에 맞는 할인율 적용해 총 금액 계산
- ⬜ 사용자 유형의 Enum 정의 및 각 사용자 유형에 따른 할인율 적용
- ⬜ 람다 & 스트림을 활용한 장바구니 조회 기능
- ⬜ 기존에 생성한 Menu의 MenuItem을 조회 할 때 스트림을 사용하여 출력하도록 수정
- ⬜ 기존 장바구니에서 특정 메뉴 빼기 기능을 통한 스트림 활용
- ⬜ 예시 : 장바구니에 SmokeShack 가 들어 있다면, stream.filter를 활용하여 특정 메뉴 이름을 가진 메뉴 장바구니에서 제거
문제 풀이
앞서 설명한 내용은 생략하겠습니다.
Main
더보기
public class Main {
public static void main(String[] args) {
Kiosk kiosk = new Kiosk();
kiosk.start();
}
}
Kiosk
더보기
import java.util.InputMismatchException;
import java.util.Scanner;
public class Kiosk {
// 속성
private final Menu menu = new Menu();
private final ShoppingBascket shoppingBascket = new ShoppingBascket();
// 생성자
public Kiosk() {
menu.addMenu(new Burger("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거", MenuType.BURGER));
menu.addMenu(new Burger("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거", MenuType.BURGER));
menu.addMenu(new Burger("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거", MenuType.BURGER));
menu.addMenu(new Burger("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거", MenuType.BURGER));
menu.addMenu(new Cake("CheeseCake", 10.4, "내가 제일 좋아하는 치즈 케이크", MenuType.CAKE));
menu.addMenu(new Cake("ChocolateCake", 5.4, "내가 제일 싫어하는 치즈 케이크", MenuType.CAKE));
}
// 기능
// 키오스크 동작
public void start() {
int mainMenuInput;
int menuInput;
int shoppingBascketInput;
do {
try {
// 메인 메뉴를 보여준다.
menu.showMainMenu();
if (!shoppingBascket.getList().isEmpty()) shoppingBascket.showOrderMenu();
// 메인 메뉴에 대한 사용자의 입력을 받는다.
System.out.print("메뉴를 선택하세요 : ");
mainMenuInput = userInput();
if (mainMenuInput == 0) {
System.out.println("종료합니다.");
return;
}
// 장바구니 메뉴가 보이지 않을 때, 전체 메뉴 갯수 보다 큰 수를 입력 시 예외 생성
if (shoppingBascket.getList().isEmpty() && mainMenuInput > menu.getTotalMenuCount()) throw new IndexOutOfBoundsException();
// 장바구니가 보일 때, 전체 메뉴 갯수 + 장바구니 메뉴 갯수(2) 보다 큰 수를 입력 시 예외 생성
if (mainMenuInput > menu.getTotalMenuCount() + 2) throw new IndexOutOfBoundsException();
// 장바구니 확인
if (mainMenuInput == menu.getTotalMenuCount() + 1) {
shoppingBascket.showShoppingBascketMenu();
System.out.println("\n1. 주문\t\t2. 메뉴 삭제\t\t3. 메뉴판");
System.out.print("주문하시겠습니까? ");
int input = userInput();
// 주문 완료
switch (input) {
case 1 -> {
int num = 1;
System.out.println("할인 정보를 입력해주세요.");
for (DiscountType discountType : DiscountType.values()) {
System.out.println(num++ + ". " + discountType.getTarget() + "\t: " + discountType.getDiscount() + "%");
}
System.out.print("입력해주세요 : ");
Discount discount = new Discount(userInput());
double totalCost = shoppingBascket.getTotalCost();
System.out.printf("주문이 완료되었습니다. 금액은 w %.2f 입니다.\n\n", discount.Calculate(totalCost));
shoppingBascket.resetTotalCost();
shoppingBascket.resetshoppingBascket();
continue;
}
case 2 -> {
Scanner scanner = new Scanner(System.in);
shoppingBascket.showShoppingBascketMenu();
System.out.print("장바구니에서 어떤 음식을 삭제하시겠습니까? ");
String food_name = scanner.nextLine();
shoppingBascket.deleteMenu(food_name);
continue;
}
case 3 -> {
System.out.println(); // 줄바꿈
continue;
}
default -> throw new IndexOutOfBoundsException();
}
}
// 주문 취소
if (mainMenuInput == menu.getTotalMenuCount() + 2) {
System.out.println("주문이 취소되었습니다.\n");
shoppingBascket.resetshoppingBascket();
continue;
}
// 메뉴를 보여준다.
menu.showMenu(mainMenuInput);
// 메뉴에 대한 사용자의 입력을 받는다.
System.out.print("메뉴를 선택하세요 : ");
menuInput = userInput();
if (menuInput == 0) {
System.out.println();
continue;
}
// 선택된 메뉴 보여주기
menu.showSelectedFood(mainMenuInput, menuInput);
// 장바구니에 추가할건지에 대한 사용자의 입력받기
System.out.println("위 메뉴를 장바구니에 추가하시겠습니까?");
System.out.println("1. 확인\t\t2. 취소");
System.out.print("추가하시겠습니까? ");
shoppingBascketInput = userInput();
// 장바구니에 추가하기
switch (shoppingBascketInput) {
case 1 -> shoppingBascket.addMenu(menu.getMenuItems(mainMenuInput, menuInput));
case 2 -> System.out.println("취소되었습니다.\n");
default -> throw new IndexOutOfBoundsException();
}
} catch (IndexOutOfBoundsException e) {
System.out.println("없는 메뉴입니다.\n");
} catch (InputMismatchException e) {
System.out.println("숫자를 입력해주세요.\n");
}
} while(true);
}
// 유저 메뉴 입력 받는 함수
private int userInput() {
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
}
}
- if문을 통해 여러 분기로 나눴던 기존 코드에서 switch 문을 사용하여, 가독성을 향상시켰다.
- 장바구니에서 특정 객체를 삭제하는 메서드를 ShoppingBascket 클래스에 만들어서 사용한다.
- 할인을 적용하기위한 메서드를 Discount 클래스에 만들어서 사용한다. (할인을 관리하기 위한 클래스를 하나 만들었다.)
ShoppingBascket
더보기
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ShoppingBascket {
List<MainMenu> shoppingBascket = new ArrayList<>();
double totalCost = 0;
public void showOrderMenu() {
int num = MenuType.values().length;
System.out.println();
System.out.println("[ ORDER MENU ]");
System.out.println(++num + " Orders\t\t | 장바구니를 확인 후 주문합니다.");
System.out.println(++num + " Cancel\t\t | 진행중인 주문을 취소합니다.");
}
public void addMenu(MainMenu mainMenu) {
System.out.println(mainMenu.getFood_name() + "이 장바구니에 추가되었습니다.\n");
shoppingBascket.add(mainMenu);
addItemPrice(mainMenu);
}
public List<MainMenu> getList() {
return shoppingBascket;
}
public void showShoppingBascketMenu() {
System.out.println("\n[ Orders ]");
for (MainMenu menu : shoppingBascket) {
System.out.println(menu.getFood_name() + " | " + menu.getPrice() + " | " + menu.getIngredients());
}
System.out.println("\n[ Total ]");
System.out.printf("w %.2f\n", totalCost);
}
public double getTotalCost() {
return totalCost;
}
private boolean isFindMenu(String name) {
for (MainMenu mainMenu : shoppingBascket) {
if(mainMenu.getFood_name().equalsIgnoreCase(name)) return true;
}
return false;
}
public void deleteMenu(String name) {
if (isFindMenu(name)) {
// 전체 비용에서 메뉴 값 만큼 삭제
subtractItemPrice(name);
shoppingBascket = shoppingBascket.stream()
.filter(menu -> !menu.getFood_name().equalsIgnoreCase(name))
.collect(Collectors.toList());
System.out.println(name + "이/가 장바구니에서 삭제되었습니다.\n");
} else {
System.out.println("음식이 존재하지 않습니다.\n");
}
}
public void addItemPrice(MainMenu mainMenu) {
totalCost += mainMenu.getPrice();
}
private void subtractItemPrice(String name) {
shoppingBascket.stream()
.filter(menu -> menu.getFood_name().equalsIgnoreCase(name))
.findAny().ifPresent(mainMenu -> totalCost -= mainMenu.getPrice());
}
public void resetshoppingBascket () {
shoppingBascket.clear();
}
public void resetTotalCost() {
totalCost = 0;
}
}
- 특정 메뉴를 삭제하는 메서드, 그 값만큼 전체 비용에서 삭제하 메서드를 만들었다.
Menu
더보기
import java.util.ArrayList;
import java.util.List;
public class Menu {
// 속성
private final List<List<MainMenu>> menuItems = new ArrayList<>();
// 생성자
public Menu() {
for(int i = 0; i < MenuType.values().length; i ++) {
menuItems.add(new ArrayList<>());
}
}
// 메뉴 추가하는 기능
public void addMenu(MainMenu newFood) {
menuItems.get(newFood.getMenuType().getNum()-1).add(newFood);
}
// 메인 메뉴 보여주는 기능
public void showMainMenu() {
int num = 1;
System.out.println("[ MAIN MENU ]");
System.out.println("0. 종료\t\t | 종료");
for(MenuType type : MenuType.values()){
System.out.println(num++ + ". " + type.name());
}
}
// 메뉴 보여주는 기능
public void showMenu(int input) {
int num = 1;
System.out.println("\n[ SHAKESHACK MENU ]");
System.out.println("0. 뒤로가기\t\t");
for (MainMenu menuItem : menuItems.get(input-1)) {
System.out.println(num++ + ". "
+ menuItem.getFood_name() + "\t | w "
+ menuItem.getPrice() + " |\t"
+ menuItem.getIngredients());
}
}
// 메뉴 정보 제공
public void showSelectedFood(int mainMenuInput, int menuInput) {
System.out.println("선택한 메뉴 : "
+ menuItems.get(mainMenuInput-1).get(menuInput-1).getFood_name() + "\t | w "
+ menuItems.get(mainMenuInput-1).get(menuInput-1).getPrice() + " |\t"
+ menuItems.get(mainMenuInput-1).get(menuInput-1).getIngredients());
System.out.println();
}
public MainMenu getMenuItems(int num, int num1) {
return menuItems.get(num-1).get(num1-1);
}
public int getTotalMenuCount() {
return MenuType.values().length;
}
}
MenuType
더보기
public enum MenuType {
BURGER(1),
DRINK(2),
DESSERT(3),
CAKE(4);
private final int num;
MenuType(int num) {
this.num = num;
}
public int getNum() {
return num;
}
}
MainMenu
더보기
public abstract class MainMenu {
private final String food_name;
private final double price;
private final String ingredients;
private final MenuType menuType;
public MainMenu(String food_name, double price, String ingredients, MenuType menuType) {
this.food_name = food_name;
this.price = price;
this.ingredients = ingredients;
this.menuType = menuType;
}
public String getFood_name() {
return food_name;
}
public double getPrice() {
return price;
}
public String getIngredients() {
return ingredients;
}
public MenuType getMenuType() {
return menuType;
}
}
Burger
더보기
public class Burger extends MainMenu {
public Burger(String food_name, double price, String ingredients, MenuType menuType) {
super(food_name, price, ingredients, menuType);
}
}
Drink
더보기
public class Drink extends MainMenu {
public Drink(String food_name, double price, String ingredients, MenuType menuType) {
super(food_name, price, ingredients, menuType);
}
}
Dessert
더보기
public class Dessert extends MainMenu {
public Dessert(String food_name, double price, String ingredients, MenuType menuType) {
super(food_name, price, ingredients, menuType);
}
}
Cake
더보기
package com.example.kiosk.challenge_2;
public class Cake extends MainMenu {
public Cake(String food_name, double price, String ingredients, MenuType menuType) {
super(food_name, price, ingredients, menuType);
}
}
DiscountType
더보기
public enum DiscountType {
VETERAN("국가 유공자", 10),
SOLDER("군인", 5),
STUDENT("학생",3),
NORMAL("일반",0);
private final String target;
private final int discount;
DiscountType(String target, int discount) {
this.target = target;
this.discount = discount;
}
public String getTarget() {
return target;
}
public int getDiscount() {
return discount;
}
}
- 각 할인율을 적용하기 위해 할인 타입을 정해주는 enum을 추가하였다.
Discount
public class Discount {
DiscountType type;
public Discount(int num) {
switch(num) {
case 1 -> type=DiscountType.VETERAN;
case 2 -> type=DiscountType.SOLDER;
case 3 -> type=DiscountType.STUDENT;
case 4 -> type=DiscountType.NORMAL;
default -> throw new IndexOutOfBoundsException();
}
}
public double Calculate(double totalCost) {
return totalCost - totalCost*(type.getDiscount()*0.01);
}
}
- 입력받은 값을 통해 생성자에서 할인 타입을 만들어주었다.
- Kiosk 클래스에서 예외처리를 한 번에 해주기 위해, RuntimeException의 자식인 IndexOutOfBoundsException을 생성하고 던져주었다.
- Calculate() 메서드를 통해 할인율이 적용된 값을 반환해준다.
'JAVA' 카테고리의 다른 글
[Java] Lv_2 도서관 프로젝트 (0) | 2025.05.01 |
---|---|
[Java] Lv_1 도서관 프로젝트 (0) | 2025.05.01 |
[Java] 제네릭(Generic), 왜 사용할까? (0) | 2025.04.28 |
[Java] 도전 과제 Lv_1 키오스크 (0) | 2025.04.26 |
[Java] Lv_4 & 5 키오스크 문제 (0) | 2025.04.25 |