✅ 객체 지향 설계를 적용해 음식 메뉴와 주문 내역을 클래스 기반으로 관리하고 캡슐화 적용
Menu클래스 생성하기
- 설명 : MenuItem 클래스를 관리하는 클래스이다
예를 들어, 버거 메뉴, 음료 메뉴 등 각 카테고리 내에 여러MenuItem을 포함한다.List<MenuItem>은Kiosk클래스가 관리하기에 적절하지 않으므로 Menu 클래스가 관리하도록 변경한다.- 여러 버거들을 포함하는 상위 개념 ‘버거’ 같은
카테고리 이름필드를 갖는다.- 메뉴 카테고리 이름을 반환하는 메서드가 구현되어야 한다.
- Getter와 Setter 메서드를 사용해 데이터를 관리한다.
package Lv4;
public class Lv4Main {
public static void main(String[] args) {
Lv4Menu lv4Menu = new Lv4Menu();
lv4Menu.getLv4Menus().add(new Lv4Menu("Burgers"));
lv4Menu.getLv4Menus().add(new Lv4Menu("Drinks"));
lv4Menu.getLv4Menus().add(new Lv4Menu("Desserts"));
// Lv4Menu 에 있는 burgersMenu 라는 리스트에 getter 를 사용해 햄버거 정보를 추가
lv4Menu.getBurgersMenu().add(new Lv4MenuItem("ShackBurger", 6.9, "토마토, 양상추, 쉑소스가 토핑된 치즈버거"));
lv4Menu.getBurgersMenu().add(new Lv4MenuItem("SmokeShack", 8.9, "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거"));
lv4Menu.getBurgersMenu().add(new Lv4MenuItem("Cheeseburger", 6.9, "포테이토 번과 비프패티, 치즈가 토핑된 치즈버거"));
lv4Menu.getBurgersMenu().add(new Lv4MenuItem("Hamburger", 5.4, "비프패티를 기반으로 야채가 들어간 기본버거"));
// Lv4Menu 에 있는 drinksMenu 라는 리스트에 getter 를 사용해 음료 정보를 추가
lv4Menu.getDrinksMenu().add(new Lv4MenuItem("Fountain Soda", 2.9, "코카콜라, 코카콜라 제로, 스프라이트, 환타 오렌지"));
lv4Menu.getDrinksMenu().add(new Lv4MenuItem("Lemonade", 4.5, "매장에서 직접 만드는 상큼한 레몬에이드"));
lv4Menu.getDrinksMenu().add(new Lv4MenuItem("Fresh Brewed Iced Tea", 3.7, "직접 유기농 홍차를 우려낸 아이스 티"));
lv4Menu.getDrinksMenu().add(new Lv4MenuItem("Fifty/Fifty", 4.0, "레몬에이드와 유기농 홍차를 우려낸 아이스 티가 만나 탄생한 시그니처 음료"));
// Lv4Menu 에 있는 dessertsMenu 라는 리스트에 getter 를 사용해 디저트 정보를 추가
lv4Menu.getDessertsMenu().add(new Lv4MenuItem("Shack Attack", 6.2, "진한 초콜릿 커스터드에 퍼지 소스와 세 가지 초콜릿 토핑이 블렌딩된 콘크리트"));
lv4Menu.getDessertsMenu().add(new Lv4MenuItem("Classic Hand-Spun Shakes", 6.8, "쫀득하고 진한 커스터드가 들어간 클래식 쉐이크"));
lv4Menu.getDessertsMenu().add(new Lv4MenuItem("Cup & Cones", 5.7, "신선하게 제조하는 쫀득하고 진한 아이스크림"));
Lv4Kiosk lv4Kiosk = new Lv4Kiosk(lv4Menu);
lv4Kiosk.start(); // Lv4Kiosk 에 있는 start 함수 실행
}
}
package Lv4;
public class Lv4MenuItem {
// 1. 속성
private String name;
private double price;
private String foodDetails;
// 2. 생성자
public Lv4MenuItem(String name, double price, String foodDetails) {
this.name = name;
this.price = price;
this.foodDetails = foodDetails;
}
// 3. 기능
// 주소값을 출력하는 것이 아닌 리스트안에 들어있는 값을 출력하기 위해 toString 메서드 작성
public String toString() {
return name + " | " + "W" + price + " | " + foodDetails;
}
}
package Lv4;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Lv4Kiosk {
Lv4Menu lv4Menu;
Scanner scanner = new Scanner(System.in);
// 2. 생성자
public Lv4Kiosk(Lv4Menu lv4Menu) {
this.lv4Menu = lv4Menu;
}
// 3. 기능(메서드)
public void start() { // 입력과 반복문 로직
while (true) { // 사용자가 종료를 누르기 전까지 계속 반복
int num1 = 0;
int num2 = 0;
System.out.println("\n");
lv4Menu.mainMenu();
while (true) {
System.out.print("\n");
System.out.print("원하시는 메뉴를 선택해주세요: ");
try {
num1 = scanner.nextInt();
if (num1 < 0 || num1 > 3) {
throw new IllegalArgumentException();
}
break;
} catch (IllegalArgumentException | InputMismatchException e) {
System.out.println("올바른 숫자를 입력해주세요.");
scanner.nextLine();
}
}
if (num1 == 0) {
System.out.println("프로그램을 종료합니다.");
break; //종료
}
while (true) {
System.out.println("\n");
if (num1 == 1) {
lv4Menu.burgersMenu();
} else if (num1 == 2) {
lv4Menu.drinkMenu();
} else if (num1 == 3) {
lv4Menu.dessertsMenu();
}
try { // 다른 값을 입력했을 시 예외처리
System.out.print("원하시는 메뉴를 선택해주세요: ");
num2 = scanner.nextInt();
if (num2 == 0) break; // 0을 입력하면 메인메뉴로 돌아가게 된다.
if (num1 == 1) {
System.out.println("선택한 메뉴: " + lv4Menu.getBurgersMenu().get(num2 - 1));
} else if (num1 == 2) {
System.out.println("선택한 메뉴: " + lv4Menu.getDrinksMenu().get(num2 - 1));
} else if (num1 == 3) {
System.out.println("선택한 메뉴: " + lv4Menu.getDessertsMenu().get(num2 - 1));
}
} catch (IndexOutOfBoundsException | InputMismatchException e) {
System.out.println("올바른 숫자를 입력해주세요");
scanner.nextLine(); // 버퍼에 남아있는 값을 제거하기 위해 사용
}
}
}
}
}
package Lv4;
import java.util.ArrayList;
import java.util.List;
public class Lv4Menu {// MenuItem 클래스를 관리하는 클래스
// 1. 속성
private final List<Lv4MenuItem> burgersMenu = new ArrayList<>();
private final List<Lv4MenuItem> drinksMenu = new ArrayList<>();
private final List<Lv4MenuItem> dessertsMenu = new ArrayList<>();
private final List<Lv4Menu> lv4Menus = new ArrayList<>();
private String name;
// 2. 생성자
public Lv4Menu() {
}
public Lv4Menu(String name) {
this.name = name;
}
// 3. 기능(메서드)
public void burgersMenu() {
System.out.println("[ BURGERS MENU ]");
for (int i = 0; i < burgersMenu.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(burgersMenu.get(i));
}
System.out.println("0. 뒤로가기");
}
public void mainMenu() {
System.out.println("[ MAIN MENU ]");
for (int i = 0; i < lv4Menus.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(lv4Menus.get(i));
}
System.out.println("0. 종료");
}
public void drinkMenu() {
System.out.println("[ DRINKS MENU ]");
for (int i = 0; i < drinksMenu.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(drinksMenu.get(i));
}
System.out.println("0. 뒤로가기");
}
public void dessertsMenu() {
System.out.println("[ DESSERTS MENU ]");
for (int i = 0; i < dessertsMenu.size(); i++) {
System.out.print(i + 1 + ". ");
System.out.println(dessertsMenu.get(i));
}
System.out.println("0. 뒤로가기");
}
public String toString() {
return name;
}
public List<Lv4MenuItem> getBurgersMenu() {
return burgersMenu;
}
public List<Lv4MenuItem> getDrinksMenu() {
return drinksMenu;
}
public List<Lv4MenuItem> getDessertsMenu() {
return dessertsMenu;
}
public List<Lv4Menu> getLv4Menus() {
return lv4Menus;
}
}
Lv4Main클래스에서Lv4Kiost객체화를 시켜Lv4Kiost의start()함수를 실행 시켰을 때 Main 에서 리스트에 넣은 값이 출력되지 않는 상황
객체를 생성할 때
Lv4Kiosk lv4Kiosk = new Lv4Kiosk();처럼 기본 생성자를 사용한 경우start()함수에서menuItems를 출력하려고 해도 값이 없어서 아무것도 출력되지 않은 것이다.
Lv4Kiosk lv4Kiosk = new Lv4Kiosk(lv4Menu);를 사용해서menuItems를 올바르게 초기화화 하면start()함수에서List의 값을 정상적으로 출력할 수 있게 되었다.
기본 생성자와매개변수 생성자의 차이를 확실히 이해하였고 객체가 제대로 초기화되지 않으면 예상한 대로 동작하지 않는다는 점 배우게 되었다. 문제 해결을 위해 생성자 사용법을 잘못 적용했을 때 발생할 수 있는 오류를 경험하며 객체 지향 프로그래밍에서 초기화와 값을 전달하는 과정이 얼마나 중요한지 깨달았다. 게터(getter)를 사용하면서 객체의 상태를 안전하게 가져오는 방법을 배우고 직접 값을 수정하는 대신 안전하게 접근하는 방법을 익히게 되었다.