-
[과제] 키오스크 도전 Lv1내일배움캠프/과제 2025. 3. 13. 16:30
✅ Lv1. 장바구니 및 구매하기 기능을 추가하기
1️⃣ 과제 조건
- 요구사항이 가지는 의도
- 의도: 클래스 간 연계를 통해 객체 지향 프로그래밍의 기본적인 설계를 익히고, 사용자 입력에 따른 프로그램 흐름 제어와 상태 관리를 학습
- 목표
- 클래스 간 역할 분리를 이해하고, 적절히 협력하는 객체를 설계
- 프로그램 상태 변경 및 데이터 저장을 연습
- 사용자 입력에 따른 예외 처리와 조건 분기를 연습
- 장바구니 생성 및 관리 기능
- 사용자가 선택한 메뉴를 장바구니에 추가할 수 있는 기능을 제공합니다.
- 장바구니는 메뉴명, 수량, 가격 정보를 저장하며, 항목을 동적으로 추가 및 조회할 수 있어야 합니다.
- 사용자가 잘못된 선택을 했을 경우 예외를 처리합니다(예: 유효하지 않은 메뉴 번호 입력)
- 장바구니 출력 및 금액 계산
- 사용자가 결제를 시도하기 전에, 장바구니에 담긴 모든 메뉴와 총 금액을 출력합니다.
- 출력 예시
- 각 메뉴의 이름, 가격, 수량
- 총 금액 합계
- 장바구니 담기 기능
- 메뉴를 클릭하면 장바구니에 추가할 지 물어보고, 입력값에 따라 “추가”, “취소” 처리합니다.
- 메뉴는 한 번에 1개만 담을 수 있습니다.
- 장바구니에 담은 목록을 출력합니다.
- 메뉴를 클릭하면 장바구니에 추가할 지 물어보고, 입력값에 따라 “추가”, “취소” 처리합니다.
- 주문 기능
- 장바구니에 담긴 모든 항목을 출력합니다.
- 합산하여 총 금액을 계산하고, “주문하기”를 누르면 장바구니를 초기화합니다.
2️⃣ 구현 포인트
1. 장바구니 클래스 생성
- 선택한 MenuItem 의 정보를 List에 add 시킬 클래스 생성
public class Order {private final List<MenuItem> orderList;public Order() {this.orderList = new ArrayList<>();}// 장바구니 추가public void addOrder(MenuItem order) {this.orderList.add(order);}// 장바구니 비우기public void clearOrder() {this.orderList.clear();}// 장바구니 empty 여부public boolean isEmptyOrder() {return this.orderList.isEmpty();}}2. 장바구니에 물건이 있을 시 Order 메뉴 출력
- 장바구니에 물건이 없으면 Order 을 진행할 이유가 없기에 있는지 검사 후 메뉴 출력
- Main menu 선택도 Order 메뉴 출력, 미출력에 따라 검증
while (true) {this.printMainMenu(); // MAIN MENU 목록 출력 함수 실행int menuNo;if (order.isEmptyOrder()) { // 장바구니가 비어있을 경우System.out.println(String.format("%-12s | 종료\n", "0. 종료"));menuNo = inputHandler.getUserInput(br, menuListSize, true); // inputHandler 실행} else { // 장바구니에 물건이 있을 경우this.printOrderMenu(); // ORDER MENU 출력System.out.println(String.format("%-12s | 종료\n", "0. 종료"));menuNo = inputHandler.getUserInput(br, menuListSize + 2, true); // inputHandler 실행}if (menuNo == 0) { // 0 이면 프로그램 종료break;}if (!order.isEmptyOrder() && menuNo > menuListSize) { // ORDER MENU 선택시if (menuNo == menuListSize + 1) { // Orders 버튼this.processOrder(br); // 주문 프로세스 실행} else { // Cancel 버튼order.clearOrder(); // 장바구니 초기화System.out.println("\n! 주문이 취소되었습니다 ! ");}} else { // MAIN MENU 선택 시 1this.processMenuSelection(br, menuList.get(menuNo - 1)); // 선택한 Menu 진행}}3. getUserInput 리팩토링
- 장바구니 기능을 추가하면서 선택지에 0이 없는 번호 입력받기가 생김
- 기존 기능을 그대로 살리고 싶어서 useZero 라는 파라미터 추가
public class InputHandler {public int getUserInput(BufferedReader br, int maxOption, boolean useZero) throws IOException {while (true) {System.out.print("번호를 선택해주세요 : ");String input = br.readLine();if (isValidInput(input, maxOption, useZero)) {return Integer.parseInt(input);}System.out.println("\n! 올바른 번호를 입력해주세요 !\n");}}// valid inputprivate boolean isValidInput(String input, int maxOption, boolean useZero) {try {int number = Integer.parseInt(input);return useZero ? (number >= 0 && number <= maxOption) : (number > 0 && number <= maxOption);} catch (NumberFormatException e) {return false;}}}4. processMenuSelection 장바구니 추가 로직
- 메뉴를 선택하면 장바구니에 추가할건지 선택하는 로직 구현
- 취소 시 해당 메뉴 목록 재출력
private void processMenuSelection(BufferedReader br, Menu menu) throws IOException {while (true) {System.out.printf("\n[ %s MENU ]\n", menu.getCategory().toUpperCase()); // 선택한 메뉴 출력menu.printMenuItemList(); // 선택한 메뉴의 menuItem List 출력int itemNo = inputHandler.getUserInput(br, menu.getMenuItemsSize(), true); // 입력받기if (itemNo != 0) { // 메뉴 선택시menu.printMenuItemDetails(itemNo - 1); // menuItem Detail 출력MenuItem menuItem = menu.getMenuItemByIndex(itemNo - 1); // menuItem 가져 옴System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");System.out.println("1. 확인 2. 취소\n");int orderNo = inputHandler.getUserInput(br, 2, false); // 입력받기if (orderNo == 1) { // 장바구니 추가System.out.println(menuItem.getMenuNm() + " 이 장바구니에 추가되었습니다.");order.addOrder(menuItem);break;}System.out.println("취소 되었습니다.");} else { // 돌아가기 선택 시break;}}}5. processOrder
- 주문시 장바구니 목록 출력
- 총 금액 출력은 stream()함수의 sum() 함수를 이용하여 list의 모든 price 를 합쳐서 return
private void processOrder(BufferedReader br) throws IOException {System.out.println("\n아래와 같이 주문 하시겠습니까?\n");order.printOrderList(); // 장바구니 List 출력order.printTotalPrice(); // 총 금액 출력System.out.println("\n1. 주문 2. 메뉴판\n");int no = inputHandler.getUserInput(br, 2, false);if (no == 1) { // 주문 진행order.order();}}// 메뉴 목록 출력 함수public void printOrderList() {System.out.println("[ Orders ]");for (MenuItem order : orderList) {System.out.println(order);}}// 총 금액 출력 함수public void printTotalPrice() {System.out.println("\n[ Total ]");System.out.printf("W %.1f\n", this.getTotalPrice());}public Double getTotalPrice() {return orderList.stream().mapToDouble(MenuItem::getPrice).sum();}3️⃣ 최종 코드
1. Main
import java.util.ArrayList;import java.util.List;public class Main {public static void main(String[] args) {List<Menu> menuList = new ArrayList<>();// BurgersmenuList.add(new Menu("Burgers", List.of(new MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"),new MenuItem("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"),new MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"),new MenuItem("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거"))));// DrinksmenuList.add(new Menu("Drinks", List.of(new MenuItem("Coke", 2.5, "탄산이 가득한 코카콜라"),new MenuItem("Cider", 2.5, "청량미 넘치는 사이다"),new MenuItem("Lemon juice", 3.0, "생과일 레몬이 들어간 레몬 쥬스"),new MenuItem("PowerAde", 3.0, "수분을 보충시켜 줄 파워에이드"))));// DessertsmenuList.add(new Menu("Desserts", List.of(new MenuItem("Cheese Cake", 5.0, "꾸덕한 치즈가 들어간 치즈 케이크"),new MenuItem("Chocolate cake", 5.5, "초코가 흘러내리는 달콤한 초콜릿 케이크"),new MenuItem("IceCream", 3.0, "시원한 아이스크림"),new MenuItem("Cookie", 2.0, "갓 구운 바삭한 쿠키"))));new Kiosk(menuList).start();}}2. Menu
import java.util.List;public class Menu {private final String category; // 카테고리private final List<MenuItem> menuItems; // menu Item 목록public Menu(String category, List<MenuItem> menuItems) {this.category = category;this.menuItems = menuItems;}public String getCategory() {return category;}public int getMenuItemsSize() {return menuItems.size();}// MenuItem 목록 출력public void printMenuItemList() {for (int i = 0; i < menuItems.size(); i++) {System.out.println((i + 1) + ". " + menuItems.get(i));}System.out.println("0. 뒤로가기\n");}// menuItem detail 출력public void printMenuItemDetails(int index) {MenuItem item = this.getMenuItemByIndex(index);System.out.printf("선택한 메뉴 : %s | 가격 : W %.1f | 설명 : %s\n",item.getMenuNm(), item.getPrice(), item.getDesc());}public MenuItem getMenuItemByIndex(int index) {return menuItems.get(index);}}3. MenuItem
public class MenuItem {private final String menuNm; // 메뉴명private final double price; // 가격private final String desc; // 설명public MenuItem(String menuNm, double price, String desc) {this.menuNm = menuNm;this.price = price;this.desc = desc;}public String getMenuNm() {return menuNm;}public double getPrice() {return price;}public String getDesc() {return desc;}@Overridepublic String toString() {return String.format("%-13s | W %-4.1f | %s", menuNm, price, desc);}}4. Order
import java.util.ArrayList;import java.util.List;public class Order {private final List<MenuItem> orderList;public Order() {this.orderList = new ArrayList<>();}// 장바구니 추가public void addOrder(MenuItem order) {this.orderList.add(order);}// 장바구니 비우기public void clearOrder() {this.orderList.clear();}// 장바구니 empty 여부public boolean isEmptyOrder() {return this.orderList.isEmpty();}// 메뉴 목록 출력 함수public void printOrderList() {System.out.println("[ Orders ]");for (MenuItem order : orderList) {System.out.println(order);}}// 총 금액 출력 함수public void printTotalPrice() {System.out.println("\n[ Total ]");System.out.printf("W %.1f\n", this.getTotalPrice());}// 총 금액 sum 함수public Double getTotalPrice() {return orderList.stream().mapToDouble(MenuItem::getPrice).sum();}public void order() {System.out.printf("\n주문이 완료되었습니다. 금액은 W %.1f 입니다.\n", this.getTotalPrice());this.clearOrder(); // 장바구니 초기화}}5. InputHandler
import java.io.BufferedReader;import java.io.IOException;public class InputHandler {public int getUserInput(BufferedReader br, int maxOption, boolean useZero) throws IOException {while (true) {System.out.print("번호를 선택해주세요 : ");String input = br.readLine();if (isValidInput(input, maxOption, useZero)) {return Integer.parseInt(input);}System.out.println("\n! 올바른 번호를 입력해주세요 !\n");}}// valid inputprivate boolean isValidInput(String input, int maxOption, boolean useZero) {try {int number = Integer.parseInt(input);return useZero ? (number >= 0 && number <= maxOption) : (number > 0 && number <= maxOption);} catch (NumberFormatException e) {return false;}}}6. Kiosk
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;public class Kiosk {private final List<Menu> menuList; // 메뉴 목록private final InputHandler inputHandler; // inputHandlerprivate final Order order; // 장바구니public Kiosk(List<Menu> menuList) {this.menuList = menuList;this.inputHandler = new InputHandler();this.order = new Order();}public void start() {int menuListSize = menuList.size();try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {while (true) {this.printMainMenu(); // MAIN MENU 목록 출력 함수 실행int menuNo;if (order.isEmptyOrder()) { // 장바구니가 비어있을 경우System.out.println(String.format("%-12s | 종료\n", "0. 종료"));menuNo = inputHandler.getUserInput(br, menuListSize, true); // inputHandler 실행} else { // 장바구니에 물건이 있을 경우this.printOrderMenu(); // ORDER MENU 출력System.out.println(String.format("%-12s | 종료\n", "0. 종료"));menuNo = inputHandler.getUserInput(br, menuListSize + 2, true); // inputHandler 실행}if (menuNo == 0) { // 0 이면 프로그램 종료break;}if (!order.isEmptyOrder() && menuNo > menuListSize) { // ORDER MENU 선택시if (menuNo == menuListSize + 1) { // Orders 버튼this.processOrder(br); // 주문 프로세스 실행} else { // Cancel 버튼order.clearOrder(); // 장바구니 초기화System.out.println("\n! 주문이 취소되었습니다 ! ");}} else { // MAIN MENU 선택 시 1this.processMenuSelection(br, menuList.get(menuNo - 1)); // 선택한 Menu 진행}}} catch (IOException e) {System.out.println("\n! 에러가 발생했습니다 !\n");}System.out.println("\n프로그램을 종료합니다.");}// MAIN MENU 목록 출력 함수private void printMainMenu() {System.out.println("\n[ MAIN MENU ]");int i = 1;for (Menu menu : menuList) {System.out.println(i++ + ". " + menu.getCategory());}}// ORDER MENU 목록 출력 함수private void printOrderMenu() {System.out.println("\n[ ORDER MENU ]");int i = menuList.size() + 1;System.out.println(String.format("%-13s | 장바구니를 확인 후 주문합니다.", i++ + ". Orders"));System.out.println(String.format("%-13s | 진행중인 주문을 취소합니다.", i + ". Cancel"));}// 주문 processprivate void processOrder(BufferedReader br) throws IOException {System.out.println("\n아래와 같이 주문 하시겠습니까?\n");order.printOrderList(); // 장바구니 List 출력order.printTotalPrice(); // 총 금액 출력System.out.println("\n1. 주문 2. 메뉴판\n");int no = inputHandler.getUserInput(br, 2, false);if (no == 1) { // 주문 진행order.order();}}// 메뉴 선택 후 processprivate void processMenuSelection(BufferedReader br, Menu menu) throws IOException {while (true) {System.out.printf("\n[ %s MENU ]\n", menu.getCategory().toUpperCase()); // 선택한 메뉴 출력menu.printMenuItemList(); // 선택한 메뉴의 menuItem List 출력int itemNo = inputHandler.getUserInput(br, menu.getMenuItemsSize(), true); // 입력받기if (itemNo != 0) { // 메뉴 선택시menu.printMenuItemDetails(itemNo - 1); // menuItem Detail 출력MenuItem menuItem = menu.getMenuItemByIndex(itemNo - 1); // menuItem 가져 옴System.out.println("\n위 메뉴를 장바구니에 추가하시겠습니까?");System.out.println("1. 확인 2. 취소\n");int orderNo = inputHandler.getUserInput(br, 2, false); // 입력받기if (orderNo == 1) { // 장바구니 추가System.out.println(menuItem.getMenuNm() + " 이 장바구니에 추가되었습니다.");order.addOrder(menuItem);break;}System.out.println("취소 되었습니다.");} else { // 돌아가기 선택 시break;}}}}'내일배움캠프 > 과제' 카테고리의 다른 글
[과제] 일정 관리 앱 만들기 필수 Lv1 (0) 2025.03.25 [과제] 키오스크 도전 Lv2 (2) 2025.03.13 [과제] 키오스크 필수 Lv5 (1) 2025.03.13 [과제] 키오스크 필수 Lv4 (0) 2025.03.13 [과제] 키오스크 필수 Lv3 (0) 2025.03.13 - 요구사항이 가지는 의도