본문 바로가기
언어(Language)/[자바] 객체지향 프로그래밍 심화

커피 주문하기

by 쿠키쿠 2023. 5. 10.
  • 목적 : class 이론 공부하다가 적용 연습 겸 카페 키오스크로 커피 주문하기 만들어봄

 

  • 슈도 코드 작성

- 카페에서 키오스크를 통해 커피 주문하기 -> 사용자가 커피를 선택하면 해당 번호에 커피 만들기 및 잔액 알려주기

- 잔액 부족 시 부족하다고 알리고 종료 

- 돈이 부족할 때까지 강제 구매 (1회성 구매는 단순하기에 이렇게 설정)

 

  • 작성된 코드
public class Cafe {
    public static void main(String[] args) {
        System.out.println("어서오세요 만랩 커피 입니다.");
        Customer customer = new Customer();

        while (customer.money >= 4200) {
            customer.selectCoffee();
            customer.buyCoffee();
        }

        System.out.println("잔액이 부족하여 더 이상 커피를 구매할 수 없습니다.");

    }
}

class Customer {
    Scanner scanner = new Scanner(System.in);
    int money = 20000;
    int menuNumber;

    void selectCoffee() {
        System.out.println("=== 메뉴를 선택하세요 === \n1번: 아메키라노\n2번: 카페모카\n3번: 라떼\n4번: 딸기주스");
        System.out.print("입력창 >>> ");
        menuNumber = scanner.nextInt();

        while (menuNumber < 1 || menuNumber > 4) {
            System.out.println();
            System.out.println("메뉴에 해당되는 번호만 누르세요");
            System.out.println("=========================");
            System.out.println("메뉴를 선택하세요 \n1번: 아메키라노\n2번: 카페모카\n3번: 라떼\n4번: 딸기주스");
            System.out.print("입력창 >>> ");
            menuNumber = scanner.nextInt();
        }
    }

    void buyCoffee() {
        Coffee coffee = null;

        switch (menuNumber) {
            case 1:
                coffee = new Americano();
                break;
            case 2:
                coffee = new CafeMocha();
                break;
            case 3:
                coffee = new Latte();
                break;
            case 4:
                coffee = new StrawBerryJuice();
                break;
        }

        if (coffee != null) {
            if (money < coffee.price) {
                System.out.println("*** 잔액이 부족합니다 ***");
            } else {
                System.out.println("주문하신 " + coffee.name + " 나왔습니다.");
                money -= coffee.price;
                System.out.println("남은 보유금액은 " + money + "원 입니다.");
            }
        }
    }
}

class Coffee {
    String name;
    int price;

    public Coffee(String name, int price) {
        this.name = name;
        this.price = price;
    }
}

class Americano extends Coffee {
    public Americano() {
        super("아메리카노", 4200);
    }
}

class CafeMocha extends Coffee {
    public CafeMocha() {
        super("카페모카", 4600);
    }
}

class Latte extends Coffee {
    public Latte() {
        super("라떼", 4800);
    }
}

class StrawBerryJuice extends Coffee {
    public StrawBerryJuice() {
        super("딸기주스", 5200);
    }
}

출력 결과 : 

  • 코드 리뷰 :

1. Customer 클래스에서 Scanner 객체를 멤버 변수로 선언 -> 여러 메서드에서 scanner 객체를 사용할 수 있음

2. selectCoffee() 메서드에서 메뉴 번호를 입력받을 때, 1부터 4까지의 번호만 입력받도록 while 문을 사용하여 예외 처리

3. buyCoffee() 메서드에서는 switch 문을 사용하여 커피 종류를 선택하고, 각각의 커피 종류에 대한 객체를 생성한다. 이때, 커피 종류에 따라 가격이 다르므로, Coffee 클래스를 상속받는 각각의 하위 클래스에서 가격을 정의.

4. buyCoffee() 메서드에서는 만약 커피 가격보다 현재 고객의 돈이 적다면 "잔액이 부족합니다"라는 메시지를 출력하고, 그렇지 않다면 커피를 구매하고, 고객의 돈에서 커피 가격만큼 차감.

5. Cafe 클래스에서는 while 문을 사용하여 고객이 돈이 있을 때 계속해서 커피를 주문하도록 했으며 돈이 없으면 while 문에서 빠져나가고, "잔액이 부족하여 더 이상 커피를 구매할 수 없습니다"라는 메시지를 출력.

 

  • 리팩토링 :

 Customer 클래스에 있는 buyCoffee 메서드안에서 switch문마다 주문한 커피 이름과 잔액 부족 시 잔액 알림을 출력했는데 작성하고 보니 불필요하게 코드의 중복이 발생하였다. 어떻게 처리할까 고민하다가 switch문에서 중복된 코드를 제거하고 이를 If문 밖으로 빼주었다.

// 리팩토링 전
void buyCoffee() {
        Coffee coffee;
        switch (menuNumber) {
            case 1:
                coffee = new Americano();
                if (money >= coffee.price) {
                    System.out.println("주문하신 " + coffee.name + " 나왔습니다.");
                    money -= coffee.price;
                } else {
                    System.out.println("*** 잔액이 부족합니다 ***");
                }
                break;
            case 2:
                coffee = new CafeMocha();
                if (money >= coffee.price) {
                    System.out.println("주문하신 " + coffee.name + " 나왔습니다.");
                    money -= coffee.price;
                } else {
                    System.out.println("*** 잔액이 부족합니다 ***");
                }
                break;
            case 3:
                coffee = new Latte();
                if (money >= coffee.price) {
                    System.out.println("주문하신 " + coffee.name + " 나왔습니다.");
                    money -= coffee.price;
                } else {
                    System.out.println("*** 잔액이 부족합니다 ***");
                }
                break;
            case 4:
                coffee = new StrawBerryJuice();
                if (money >= coffee.price) {
                    System.out.println("주문하신 " + coffee.name + " 나왔습니다.");
                    money -= coffee.price;
                } else {
                    System.out.println("*** 잔액이 부족합니다 ***");
                }
                break;
        }
    }
    
// 리팩토링 후 
void buyCoffee() {
        Coffee coffee = null;

        switch (menuNumber) {
            case 1:
                coffee = new Americano();
                break;
            case 2:
                coffee = new CafeMocha();
                break;
            case 3:
                coffee = new Latte();
                break;
            case 4:
                coffee = new StrawBerryJuice();
                break;
        }

        if (coffee != null) {
            if (money < coffee.price) {
                System.out.println("*** 잔액이 부족합니다 ***");
            } else {
                System.out.println("주문하신 " + coffee.name + " 나왔습니다.");
                money -= coffee.price;
                System.out.println("남은 보유금액은 " + money + "원 입니다.");
            }
        }
    }

 

 

  • 아쉬운 점 : 

1. 사실 추상 클래스와 인터페이스를 적용하기 위해서 시작한 실습인데  정작 추상 클래스와 인터페이스 적용을 못했다. 차후 추상 클래스와 인터페이스를 적용해서 다시 실습할 예정이다. 

 

2. 고객의 돈이 4200원 이상 일 경우 계속해서 키오스크로 메뉴를 선택하게 설정했는데 만약 고객의 돈이 4200원인데 그 이상의 제품을 주문하면 잔액 부족 경고와 함께 종료되길 원했지만 구현하질 못했다. 할 수 있을 것 같은데 당장 아이디어가 떠오르지 않아서 일단 미루기로 했다.

 

3. try, catch 구문을 이용해서 입력값이 잘못되었을 경우 예외를 발생시켜 catch 블록에서 처리하도록 설정하고 싶은데 하질 못했다.