키오스크 #3 - 선택 기능

김지현·2023년 10월 23일
3

JAVA

목록 보기
12/14

선택 기능

  1. 주문 개수 기능 : 장바구니에 똑같은 상품이 담기면 상품 개수가 추가되어 출력
  2. 총 판매 금액 조회 기능 : 구매가 완료될 때마다 총 판매 금액 누적
  3. 총 판매 상품 목록 조회 기능 : 구매가 완료될 때마다 판매 상품 목록 저장
  4. 상품 옵션 기능 : 상품에 옵션을 선택한 후 장바구니에 추가

주문 개수

해당 기능 구현을 위해 개수를 저장할 수 있도록 Products 클래스에 count 변수 추가 후 1로 초기화했다. 장바구니에 추가 시 기본값으로 1개로 표시되도록 했으며 이미 존재하는 상품일 경우 존재 여부를 확인한 뒤 해당 상품 객체의 count++를 해주는 방식으로 구현했다.

public void addList(Products p) {
(생략...)
	if(orderList.contains(p)) p.addCount();     // 장바구니에 동일 상품 존재시 conunt++
    else orderList.add(p);                      // 없으면 추가
(생략...)
}
  • 주문 화면

총 주문 현황 조회

총 판매 금액 조회 기능과 총 판매 상품 목록 조회 기능은 0번을 입력시 MaindisplayHiddenMenu 메서드가 실행되며 같이 나타도록 구현했다.
총 판매 금액은 Order가 완료될 때마다 장바구니 총 금액이 누적되어 저장되도록 했다.
총 판매 상품 목록 또한 Order가 완료될 때마다 orderList 장바구니 리스트를 그대로 totalProducts 리스트에 저장되도록 했다. 총 판매 상품 목록도 장바구니 리스트처럼 같은 상품이 다시 주문될 경우 count를 추가해 표시하도록 구현했다.

// Ordre 완료 시 총 주문 현황 업데이트
public void displayOrder(){
Main.totalPrice += this.totalPrice;     // 총 주문금액 업데이트

	for(Products p : orderList){            // 총 주문내역 업데이트
			if(Main.totalProducts.containsValue(p)){                    // 내역에 이미 존재하면
                Products listP = Main.totalProducts.get(p.getName());   // 해당 객체를 찾음
                listP.setCount(listP.getCount() + p.getCount());        // count 업데이트
                listP.setPrice(listP.getPrice() + p.getPrice());        // price 업데이트
            }
            else Main.totalProducts.put(p.getName(), p);                // 존재하지 않으면 put
        }

}

// 0번 선택시 총 주문 화면 출력
 public static void displayHiddenMenu(){
        // 총 주문 현황 확인
        System.out.println("[ 총 판매금액 현황 ]");
        System.out.println("현재까지 총 판매된 금액은 [ \u20A9 " + totalPrice + " ] 입니다.\n");

        System.out.println("[ 총 판매상품 목록 현황 ]");
        for(Products p : totalProducts.values())
            System.out.println("- " + p.getName() + " | \u20A9 " + p.getPrice() + " | " + p.getCount() + "개");
}
  • 히든 메뉴 화면

상품 옵션 기능

이 기능은 위에 기능들보단 구현에 시간이 조금 더 걸렸다.
해당 기능을 구현하기 위해 생각한 방법

  1. 장바구니 추가시에만 옵션 확인 후 장바구니에서는 옵션에 따른 추가금액만 표시
  2. 옵션 선택에 따른 이름과 가격으로 새로운 객체 생성
  3. getter와 setter를 이용해 객체 값 변경하여 사용

1, 2, 3번 모두 시도했는데 3번은 객체의 값 자체를 변경하므로 옵션 선택시마다 값을 일시적으로 바꾸어 사용하는 것이 불가능. 1번은 가장 간단하지만 장바구니에서는 선택한 옵션이 보이지 않는 것이 아쉬워 구현 후 2번으로 변경하였다.

옵션 저장

우선 products 객체 생성 시에 option이 있는 경우 option을 같이 저장할 수 있도록 생성자 추가, 받은 option들은 각각의 products 객체 내의 map <옵션 이름, 옵션 가격> 형태로 저장

public class Products extends Menu {
    public Map<String, Integer> options = null;		// 옵션이 없을 경우 null

    // 생성자 추가, options를 가변인자로 받음
    public Products(String name, String script, int price, Object...options) {
        super(name, script);
        this.price = price;

        this.options =  new LinkedHashMap<>();		// map 생성
        for(int i = 0; i < options.length; i+=2) {
            String key = (String) options[i];			// 첫번째 값 : String 형변환
            Integer value = (Integer) options[i + 1];	// 두번째 값 : Integer 형변환
            this.options.put(key, value);			// map에 추가
        }
    }
}

main(){
	coffeeMenu.menuList.add(new Products("Americano", "커피", 4500, "Ice", 500, "Hot", 0));
}

1번 방법

  • 장바구니 추가시에만 옵션 확인 후 장바구니에서는 옵션에 따른 추가금액만 표시

옵션이 있을 경우 name과 price 변수를 선언하여 원래 값에 옵션에 따른 이름과 금액이 변경 및 추가되도록 하였다. 지역 변수이므로 매 선택마다 초기화하여 사용된다.

 public void addList(Products p){
 	if(p.options != null){                  // 옵션이 존재할 경우
    	System.out.println("\n위 메뉴의 어떤 옵션으로 추가하시겠습니까?");

    	int i = 1;
    	for(String key : p.options.keySet())    // 옵션 map 출력
    		System.out.println("옵션 출력");

    	System.out.print("\n옵션 선택 : ");
    	int op_select = sc.nextInt();            

    	String name = p.getName() + "(" + op_select + ")";	// name을 상품 이름+(옵션 이름)으로 저장
    	price += p.options.get(op_select);			// 현재 상품 값에 옵션 값을 더해 저장
    	optionPrice += p.options.get(op_select);	// 전체 옵션 추가금 업데이트

    	System.out.println("상품 정보 출력");
 }

이후 저장한 optionPrice값을 display() 메서드 부분에서 같이 실행해주면 된다. 이 경우, 장바구니 목록이 각각 다음과 같이 보여진다.

// 장바구니 목록
[ Orders ]
Americano |4500 | 1| 에스프레소와 물을 섞은 커피

옵션 추가금 =500

[ Total ]5000

이렇게 구성한 이유는 [ 총 판매상품 목록 ]에 Americano(ICE)Americano(HOT)이 따로 저장되지 않고 Americano 하나의 상품으로 저장되게 하기위해서였다. 그러나 장바구니 목록에서 옵션이 보이는 것이 더 좋을 것 같아 코드를 변경하였다.

2번 방법

  • 옵션 선택에 따른 이름과 가격으로 새로운 객체 생성

장바구니에 옵션 선택에 따른 변경된 이름과 가격을 저장하려면 객체를 변경하든지, 객체의 값을 변경해야 했다. 하나의 객체 값을 일시적으로 변경하여 사용하는 것은 getter, setter를 이용해서는 불가능하다. (다른 방법이 있을지는 모르겠다) 나는 객체를 새로 생성하는 방법을 택했다. addList(Products p) 메서드에 매개변수로 들어온 p를 옵션이 있는 경우 새 객체를 생성하여 변경해주는 것으로 구현했다. 이때 이슈가 몇 가지 발생...

첫 번째, 장바구니가 비어있을 때를 고려하지않음.
장바구니가 비어있는 경우 객체가 생성되지 않아 p가 업데이트되지 않음. if(!orderList.isEmpty()) 조건문으로 해결 (그러나 어차피 잘못된 설계였다)

두 번째, 반복문 자체를 잘못 설계...

for (Products find_p : orderList) {
	if (find_p.getName().equals(name)) p = find_p;
    else p = new Products(name, script, price);
}

orderList() 에서 객체를 찾기 위해 반복문을 수행하고 같은 이름을 가진 객체가 있을 경우 p를 find_p로 변경 (중복 저장을 하지 않고 수량 추가를 하기 위함), 아닐 경우 새로운 객체를 생성...하려 했으나 이렇게 코드를 짜면 break가 없어 모든 리스트를 순회하게 되고 결국 리스트의 맨 마지막 product가 비교 대상이 된다. (그래서 자꾸 출력값에 중복된 객체가 나오더라...) 아래와 같이 변경해주었다.

p = null;									// p를 null로 초기화
for (Products find_p : orderList) {
	if (find_p.getName().equals(name)) {	// orderList에 존재할 경우
		p = find_p;							// 해당 객체를 반환
		break;
	}
}
if(p == null) p = new Products(name, script, price);	// 존재하지 않을 경우 새 객체 생성

이렇게 옵션에 대한 객체 생성 및 주문 리스트에 추가하는 부분을 구현하였다.
또한, 옵션을 입력받는 형식을 String에서 int로 변경하였다. (다른 메뉴는 모두 int로 입력받기 때문) Map은 인덱스 값으로 접근하는 기능을 제공하지 않으므로 옵션 선택시 입력받은 숫자로 객체를 찾는 부분은 직접 구현해주었다. 우선 입력 순서대로 저장 받도록 LinkedHashMap을 사용하였고 반복문을 통해 map을 전체 순회하며 입력받은 숫자와 인덱스 번호가 일치하는 경우 해당하는 옵션을 Map에서 불러와 사용하였다.

for(String key : p.options.keySet()){              
	if(op_select == j++){   	// map에서op_select번째 값 탐색                
    	String name = p.getName() + "(" + key + ")";        // name을 상품 이름+(옵션 이름)으로 저장
        int price = p.getPrice() + p.options.get(key);      // 현재 상품 값인 price에 옵션 값을 더해 저장
    }

결론

2번 방법을 이용해 옵션 선택 부분을 selectOption(Products p) 메서드로 구현. 이 메서드는 변경된 p를 반환하여 addList(Produts p) 메서드 내에서 다음과 같이 동작한다.

if(p.options != null) {			// 옵션이 존재할 경우
	p = selectOption(p);        // 상품 객체(p) 변경
}
  • 주문 화면
  • 장바구니 화면

Q

장바구니에서는 Americano(ICE)Americano(HOT)이 따로 보여지지만 [ 총 판매 목록 ] 에는 Americano 2개로 표시되게 하려면 어떻게 해야할까? 히든 리스트를 따로 만들어서 주문시 장바구니에는 Americano(ICE) 객체, 히든 리스트에는 Americano 객체가 저장되도록 하고 히든 리스트를 총 판매 리스트에 모두 저장하는 방법을 생각하기는 했는데 좋은 방법인지 잘 모르겠다.

profile
Server Developer

0개의 댓글