[JAVA] 키오스크(3)

림민지·2025년 3월 11일

Today I Learn

목록 보기
22/62

[ 기존 코드의 문제점 ]

  1. Kiosk 클래스에서 메뉴 추가 및 관리까지 담당해서 복잡함
    → 메뉴를 관리하는 클래스를 만들기 Menu
  2. 키오스크에서 햄북스딱스만 선택할 수 있었음
    → 메뉴 카테고리(햄버거, 음료, 디저트)를 먼저 선택하고 그에 맞는 메뉴 띄우기
  3. 카테고리 고르는 것과 메뉴 고르는 것이 분리되었으니 뒤로가기와 종료하기를 따로 구현하기

0️⃣ 클래스다이어그램 재구성

📌 키오스크 플로우

(1) Main() 실행 kiosk.start(); 실행
(2) start() 메서드를 실행
(3) 음식 카테고리 불러와서 출력
(4) 고른 카테고리에 맞는 세부 메뉴 출력
(5) (만약Burgers 골랐으면) Burgers 에서 고른 메뉴 가격 합산, 선택했다고 알려주는 멘트 출력
(6) 다시 (3)으로 돌아가서 반복


1️⃣ 클래스 분리하기

기존에는 Koisk클래스에서 메뉴의 추가 및 관리, 키오스크의 전반적인 흐름까지 담당했다.
그러다보니 코드가 길고 매우 복잡했다.
기능을 분리해 가독성을 높이고 캡슐화하기 위해 메뉴만을 관리하는 Menu클래스를 만들어보자!

1. Kiosk 클래스에서 Menu클래스로 넘길 메서드 찾기

public class Kiosk3 {
    static private final List<MenuItem3> burgers = new ArrayList<>(); //햄버거 메뉴 리스트 만들기
    static private double totalPrice =0; //총액을 저장

    public Kiosk3(){
        burgers.add(new MenuItem3(1,"ShackBurger   ", 6.9, "토마토, 양상추, 쉑 소스가 토핑된 치즈버거"));
        burgers.add(new MenuItem3(2,"SmokeShack    ", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"));
        burgers.add(new MenuItem3(3,"Cheeseburger  ", 6.9,"포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"));
        burgers.add(new MenuItem3(4,"Hamburger     ", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거"));
    }
    //키오스크 실행하기
    public void start(){...}

    //메뉴 선택하기
    public void OrderByKiosk(){...}

    public String findMenu(int select) {...}

}

기존에는 이렇게 키오스크를 실행하는 부분과 메뉴를 추가하는 부분이 혼재되어있었다.
Kiosk클래스에서 메뉴를 관리하는 부분만 가져다가 Menu 클래스에 붙여보자

  • burgers.add(new MenuItem3("..."));
  • public String findMenu(int select) {...}
    이 두 부분을 넘기면 될 것 같다!

2. Menu 클래스

동일 패키지 내에 Menu클래스를 만든다

public class Menu {
    //햄버거 메뉴 리스트
    private final List<MenuItem4> Burgers = new ArrayList<>();
    //음료수 리스트
    private final List<MenuItem4> Drinks = new ArrayList<>();
    //디저트 리스트
    private final List<MenuItem4> Desserts = new ArrayList<>();

    public Menu(){
        Burgers.add(new MenuItem4(1,"ShackBurger   ", 6.9, "토마토, 양상추, 쉑 소스가 토핑된 치즈버거"));
        Drinks.add(new MenuItem4(1, "Lemonade", 3.9, "매장에서 직접 만드는 상큼한 레몬에이드"));
        Desserts.add(new MenuItem4(1, "Dark Chocolate Cake", 5.5,"인생은 초콜릿"));
    }

전에 Burgers리스트를 만들었던 것과 같이, List<클래스명>을 활용해 리스트를 만들고,
생성자에서add()로 메뉴를 추가하자

그리고 이렇게 추가한 메뉴를 다른 클래스에서 사용할 수 있어야하므로

    public List<MenuItem4> getBurgers() {
        return Burgers;
    }
    public  List<MenuItem4> getDrinks(){
        return Drinks;
    }
    public List<MenuItem4> getDesserts(){
        return Desserts;
    }

Getter를 사용해서 각각 리스트의 내부 요소를 가져다 쓸 수 있도록 설정했다.


2️⃣ ✨ HashMap - 카테고리 만들기

HashMap에 대해 궁금하다면 이전 포스트를 봐보자~!
🔗 https://velog.io/@minjee2758/JAVA-HashSet#4--hashmap%EC%97%90-list-%EB%84%A3%EA%B8%B0

출력시에 카테고리를 먼저 보여주고, 카테고리를 선택하면 세부 메뉴를 고를 수 있어야한다.
그러려면 카테고리를 만들어놔야겠죠?
근데,, 자바에서 리스트 안에 리스트를 넣고, 카테고리명을 꺼내 쓸 수 있으려면 어떻게 해야할까?

이때 쓸 수 있는 🥔LinkedHashMap🥔!!

1. LinkedHashMap 만들기

먼저 MenuCartegory 리스트 만들어야겠죠^^

//HashMap 이용해서 MenuCartegory 리스트에 다 넣기 - 카테고리로 활용하자
private final HashMap<String, List<MenuItem4>> MenuCartegory = new LinkedHashMap<>();

글고 이 안에 아까 만들었던 메뉴의 리스트들을 다 넣어줄거야요. put()

MenuCartegory.put("Burgers", Burgers);
MenuCartegory.put("Drinks", Drinks);
MenuCartegory.put("Desserts", Desserts);

2. getter 만들기

카테고리명을 Kiosk 클래스에서 불러와서 활용할 수 있어야하니까,getMenuCartegory()

public HashMap<String, List<MenuItem4>> getMenuCartegory(){
        int i =1;
        System.out.println("[ Main Menu ]");
        for (String s : MenuCartegory.keySet()) {
            System.out.println(i +". "+s);
            i++;
        }
        return MenuCartegory;
    }

이렇게하면 불러와서 쓸 때, 카테고리명 Burgers Drinks Desserts를 출력가능하다!
나중에 카테고리가 더 추가되어도 Menu클래스에 추가해주면 다른건 건들일 것도 없이 자동으로 나올것이다~~

menu클래스를 정비했으니 이제 Kiosk클래스도 고쳐보자


3️⃣ Kiosk 클래스 재구성

기존 기능을 Menu 클래스가 수행하고 있으니 그에 맞게 Kiosk클래스도 바꾸어보자

1. 기존에서 필요 없는 메서드 삭제

public class Kiosk4 {
    static private double totalPrice =0; //총액을 저장
    Scanner scanner = new Scanner(System.in); //스캐너 불러오기

    //키오스크 실행하기
    public void start(){...}

    //메뉴 선택하기
    public void OrderByKiosk(){...}

    public String findMenu(int select) {...}

Menu클래스로 옮긴 메서드를 삭제했다.

2. Menu클래스 활용하기

메뉴 클래스의 기능을 사용하려면 클래스를 불러와야겠죵

Menu menu = new Menu();

불러온 메뉴를 활용해보자
키오스크를 실행하면 가장 먼저 카테고리를 출력해줘야한다.
기본적으로는 이전의 OrderByKiosk와 비슷하다

  • 카테고리 출력하기
  • 메뉴 번호 입력받기(0을 입력하면 종료하기)
  • 고른 카테고리의 세부 메뉴를 출력하기
  • 잘못된 번호 입력했을때의 오류 처리

아까 설정해준 getter, getMenuCartegory()를 사용해서 카테고리를 출력해주자

public void SelectMenuCartegory(){
	while (true){
    	menu.getMenuCartegory(); //카테고리 불러오기
        System.out.println("0. 종료 | 키오스크를 종료합니다");
        //메뉴 입력 받기
        System.out.print("원하는 메뉴의 번호를 입력하세요 : ");
        int select = scanner.nextInt();
        try {
        	if (select == 0){
            	System.out.println("프로그램을 종료합니다.");
                break;
            } else {
                //<세부메뉴 출력하는 메서드 넣을 자리>
                }
                //잘못 입력했을때 에러 캐치하기
            } catch (IllegalArgumentException e){
                System.out.println("error : "+e.getMessage()); //에러 뱉기
            }
        }
    }

<출력 결과>

햄버거 키오스크를 시작합니다!
=================== [ Main Menu ] ===================
1. Burgers
2. Drinks
3. Desserts
0. 키오스크 종료
→ 원하는 메뉴의 번호를 입력하세요 : 

3. 입력값 대조 - 카테고리 이름 찾아서 뱉기

여기서 원하는 메뉴의 번호를 입력하면 카테고리에서 찾아서 어떤 카테고리를 선택한건지 출력해줘야한다
findMenuCartegory 메서드를 만들어보자
먼저 Menu클래스에서 불러와야한다

List<String> category = new ArrayList<>(menu.getMenuCartegory().keySet());

아까 getMenuCartegory()메서드를 보면 MenuCartegory를 return하는 것을 볼 수 있다. 리턴값을 활용해보자!

(1) 입력값인 select를 활용해서 만약 카테고리의 select-1번째 카테고리명이 for문의 s 카테고리명이랑 같으면 그 카테고리명을 뱉어내자
(2) 근데 카테고리 안에 없으면 오류 떤져주자

public String findMenuCartegory(int select){
	for (String s : category) { //(1) 
    	if (category.get(select-1).equals(s)){
        	return s;
            }
        }
         //(2)
        throw new IllegalArgumentException(select+"번째 메뉴는 없습니다");
    }

그러면 카테고리명도 찾고, 에러처리도 할 수 있을 것이다.
이걸 SelectMenuCartegory 메서드에 활용해보자

//SelectMenuCartegory 메서드의 else문 내부
else {
	String menuCartegory = findMenuCartegory(select);
    System.out.println("> "+ menuCartegory+"를 선택하셨습니다 <");
    ...중략

menuCartegory 변수를 선언해서 findMenuCartegory메서드를 통해 나온 값을 대입하면 어떤 카테고리를 선택했는지 사용자에게 반환해줄 수 있따!

→ 원하는 메뉴의 번호를 입력하세요 : 1
> Burgers를 선택하셨습니다 <

4️⃣ 세부 메뉴 출력하기✨SelectMenuDetail

메서드 명을 OrderByKioskSelectMenuDetail
: 이제는 카테고리, 세부메뉴가 따로 나누어져있으니까 좀 더 알아보기 쉽게 하기 위해서 메서드명을 변경했다.

SelectMenuCartegory에서 올바른 select를 선택했으면 이제 그 카테고리에 맞는 세부 메뉴를 고를 수 있어야한다.
기존의 OrderByKiosk를 활용해서 ✨SelectMenuDetail✨메서드를 구성해보자

1. 선택한 카테고리에 맞는 세부메뉴를 가져오기

SelectMenuCartegory에서 고른 카테고리에 맞게 세부메뉴를 출력해주어야 한다.
(Burgers를 선택했으면 햄버거 메뉴를, Drinks를 선택했으면 음료 메뉴리스트 출력)

그러려면 어떤 세부 메뉴가 선택되었는지 인식할 수 있어야한다.
Menu클래스에서 식별할 수 있는 메서드를 만들어보자
같은거 찾아서 뱉어내기 메서드

//카테고리에 맞는 세부 메뉴 출력하기
    public List<MenuItem4> findDetailMenu(String MenuName){
        if (MenuName.equals("Burgers")){
            return getBurgers();
        } else if (MenuName.equals("Drinks")) {
            return getDrinks();
        } else{
            return getDesserts();
        }
    }

이걸 활용해서 Kiosk 클래스의 SelectMenuDetail 메서드에 활용해보자

(1) DetailMenu 리스트를 만들어서 findMenuDetail메서드에서 찾은 세부 메뉴를 넣는다

public void SelectMenuDetail(String menuCartegory){
	List<MenuItem4> DetailMenu = menu.findDetailMenu(menuCartegory);

(2) 세부 메뉴 리스트 출력하기

찾은 세부 메뉴의 이름, 가격 설명을 하나씩 출력해주자.
그리고0을 입력하면 뒤로가기가 되어야하니까 0번 메뉴도 써주기

for (int i = 0; i<DetailMenu.size(); i++){
	System.out.println(DetailMenu.get(i).getNumbering() + ". " + DetailMenu.get(i).getName() + " " +DetailMenu.get(i).getPrice() +"W  " + DetailMenu.get(i).getDescription());
    }
System.out.println("0. 뒤로 가기")

(3) 사용자에게 원하는 메뉴 입력받기

원하는 메뉴 번호를 입력받고, 만약에 0을 선택하면 카테고리 선택으로 되돌아간다.

//메뉴 입력 받기
System.out.print("→ 원하는 메뉴의 번호를 입력하세요 : ");
int select = scanner.nextInt();
	try {
    	if (select == 0){
        	System.out.println("카테고리 선택창으로 돌아갑니다");
            } else {
            	//<올바른 번호의 세부 메뉴 선택 했을때>
                }
        } catch (IllegalArgumentException e){
                System.out.println("error : "+e.getMessage()); //에러 뱉기
            }

    }

(4) 입력받은 요소 찾기

만약 올바른 세부 메뉴 번호를 입력했으면, 그 번호에 맞는 메뉴를 출력해줘야한다.
그러기 위해서 우선 선택한 번호에 맞는 메뉴를 리스트에서 찾는 메서드를 만들자
findMenu 메서드
메서드에 리스트 DetailMenuselect를 넘겨줘서 찾을 수 있도록 한다.

//메뉴명 찾기
public String findMenu(List<MenuItem4> DetailMenu,int select) {
	if (select <0 || select >DetailMenu.size()){
    	//번호 잘못 입력했을때 에러 던져주기
    	throw new IllegalArgumentException(select+"번째 메뉴는 존재하지 않습니다");
    }
    return DetailMenu.get(select-1).getName();
    }

만약에 리스트 내부 요소 개수보다 작거나 큰 수를 입력하면 에러를 뱉고,
아니면 DetailMenu의 select-1번째 요소의 이름을 반환한ㄷ,

(5) 선택 메뉴 출력하기

비워두었던 else문 내부에 findMenu메서드를 활용해서 출력하는 로직을 만들자.

  • MenuName이라는 변수에 return받은 메뉴의 이름을 할당
  • 그 메뉴를 선택했다고 출력해주기
else {
	String MenuName = findMenu(DetailMenu, select);
    System.out.println("> "+MenuName+"를 선택하셨습니다 <");
    System.out.println();}

(6) 가격 합산하기

totalPrice 변수에 메뉴 가격을 더해주자

totalPrice += DetailMenu.get(select-1).getPrice(); //가격 합산하기

결과

profile
@lim_128

0개의 댓글