[Android / Kotlin] 키오스크 프로그램 구현 (2)

Subeen·2023년 12월 7일
0

Kotlin 문법

목록 보기
14/23

어제에 이어 키오스크 프로그램을 추가로 구현하면서 생각대로 구현하는 게 어렵다는 것을 다시 한 번 깨달았다. 이렇게 저렇게 하면 되지 않을까? 하다가도 그 생각을 그대로 구현한다는게 얼마나 힘들던지.. 🥹 지금 하고 있는 키오스크 프로그램의 경우 아직 3단계까지 밖에 못 했는데 천천히라도 남은 단계를 마저 마무리 하고 구현하면서 새로 접하는 부분들을 잘 정리해야겠다 !

AbstractMenu.kt

  • Burger, Beverage, Fried 클래스에서 공통된 개념을 표현하고자 추상 클래스를 생성하였다.
  • 메뉴 아이템의 정보(id=아이템 번호, category=아이템 종류, name=이름, price=가격, explain=설명)와 아이템 정보를 출력하는 displayInfo() 추상 메소드가 포함되어 있다.

처음에는 name, price, explain 속성만 사용하려고 했는데 카테고리별 아이템을 출력할 때 아이템의 인덱스값이나 아이템을 검색하는 부분에 있어서 문제가 발생하여 인덱스와 문자열 타입의 카테고리를 추가하게 되었다.

abstract class AbstractMenu(val id: Int, val category: String, val name: String, val price: Int, val explain: String) {
    abstract fun displayInfo(): String
}
  • AbstractMenu 추상 클래스를 상속 받은 하위 클래스들을 abstractMenu객체로 받아 외부로부터 fun displayInfo()를 호출할시 abstractMenu 객체의 displayInfo() 함수를 호출한다.
class MenuManage(private val abstractMenu: AbstractMenu) {
    fun displayInfo(): String {
        return abstractMenu.displayInfo()
    }
}

ProductManage.kt

  • initProduct() : Burger, Beverage, Fried 세 개의 클래스를 상위 클래스로 묶어 하나의 리스트로 여러 개의 클래스를 관리하며 세 개의 카테고리의 메뉴 아이템을 리스트에 저장한다.
  • displayMain() : 메인 메뉴를 출력하는 함수
  • displayMenu(menu: String) : 문자열 타입의 카테고리를 전달 받아 해당 카테고리에 해당 되는 메뉴의 정보를 출력한다.
  • displayItem(item: AbstractMenu?) : 선택 된 메뉴의 아이템을 출력하는 함수
  • getSelectedItem(menu: String, id: Int): AbstractMenu? : 선택 된 아이템의 전체 정보를 반환하는 함수
  • getMenuCount(menu: String): Int : 문자열 타입의 카테고리를 전달 받아 해당 카테고리의 전체 개수를 반환하는 함수
class ProductManage {
    private val products: ArrayList<AbstractMenu> = initProduct()

    private fun initProduct(): ArrayList<AbstractMenu> {
        val products = ArrayList<AbstractMenu>()

        val burger = arrayListOf<AbstractMenu>(
            Burger(0, "burger", "빅맥", 5500, "100% 순 쇠고기 패티 두 장에 치즈, 양상추, 피클"),
            Burger(1, "burger", "맥크리스피 디럭스 버거", 6800, "100% 통다리살 케이준 치킨 패티, 포테이포 브리오쉬 번"),
            Burger(2, "burger", "맥크리스피 상하이 버거", 5500, "100% 닭가슴살 통살 위에 양상추, 토마토, 치킨 패티")
        )

        val beverage = arrayListOf<AbstractMenu>(
            Beverage(0, "beverage", "아메리카노", 1000, "바로 내린 100% 친환경 커피로 더 신선하게! 더 풍부하게!", "스몰"),
            Beverage(1, "beverage", "아메리카노", 1500, "바로 내린 100% 친환경 커피로 더 신선하게! 더 풍부하게!", "미디엄"),
            Beverage(2, "beverage", "카페라떼", 1500, "바로 내린 100% 친환경 커피가 신선한 우유를 만나 더 신선하고 부드럽게!", "스몰") ,
            Beverage(3, "beverage", "카페라떼", 2000, "바로 내린 100% 친환경 커피가 신선한 우유를 만나 더 신선하고 부드럽게!", "미디엄"),
            Beverage(4, "beverage", "코카콜라", 1700, "갈증해소 뿐만이 아니라 기분까지 상쾌하게! 코카-콜라", "스몰"),
            Beverage(5, "beverage", "코카콜라", 2200, "갈증해소 뿐만이 아니라 기분까지 상쾌하게! 코카-콜라", "미디엄")
        )

        val fried = arrayListOf<AbstractMenu>(
            Fried(0, "fried", "골든 모짜렐라 치즈스틱", 2000, "자연 모짜렐라 치즈로 빈틈 없이 고소한 치즈스틱", "2조각"),
            Fried(1, "fried", "골든 모짜렐라 치즈스틱", 4200, "자연 모짜렐라 치즈로 빈틈 없이 고소한 치즈스틱", "4조각"),
            Fried(2, "fried", "맥너겟", 2600, "바삭하고 촉촉한 치킨이 한 입에 쏙", "4조각"),
            Fried(3, "fried", "맥너겟", 3800, "바삭하고 촉촉한 치킨이 한 입에 쏙", "6조각"),
        )

        products.addAll(burger)
        products.addAll(beverage)
        products.addAll(fried)

        return products
    }

    fun displayMain() {
        val category = arrayListOf("Burger", "Side & Dessert", "Mac Cafe & Beverage")
        val explain = arrayListOf(
            "주문 즉시 바로 조리해 더욱 맛있는, 맥도날드의 다양한 버거를 소개합니다.",
            "버거와 함께 즐기면 언제나 맛있는 사이드와 디저트 메뉴!",
            "언제나 즐겁게, 맥카페와 다양한 음료를 부담없이 즐기세요!"
        )
        println(
            "\n아래 메뉴판을 보시고 메뉴를 골라 입력해주세요. \n\n" +
                    "[ McDonald's's MENU ]"
        )
        for (i in category.indices) {
            println("%d. %-20s | %s".format(i + 1, category[i], explain[i]))
        }
        println("%d. %-20s | %s".format(0, "종료", "프로그램 종료"))
    }


    fun displayMenu(menu: String) {  // 선택된 메뉴
        products.filter { it.category == menu }.forEach {
            println("${it.id + 1}. ${MenuManage(it).displayInfo()}")
        }
        println("%d. %-10s | %s".format(0, "뒤로가기", "뒤로가기"))
    }

    fun displayItem(item: AbstractMenu?) {
        if (item == null) {
            println("선택한 상품이 존재하지 않습니다. 관리자에게 문의해주세요.")
        } else {
            println("\" ${item.displayInfo()} \"")
            item.displayInfo()
            // println("위 메뉴를 장바구니에 추가하시겠습니까?")
        }
    }

    fun getSelectedItem(menu: String, id: Int): AbstractMenu? {
        return products.filter { it.category == menu }.find { it.id == id - 1 }
    }

    fun getMenuCount(menu: String): Int {
        return products.count { it.category == menu }
    }
}

Beverage.kt

  • 음료 메뉴 정보를 가지고 있는 클래스로 AbstractMenu 추상 클래스의 속성과 함수를 상속 받아 사용한다.
  • displayInfo() 함수에서 음료 메뉴의 이름, 가격, 설명, 사이즈 정보의 문자열을 반환한다.
class Beverage(id: Int, category: String, name: String, price: Int, explain: String, private val size: String) :
    AbstractMenu(id, category, name, price, explain) {
    override fun displayInfo(): String {
        return "%s - %-5s| ₩ %4d | %s".format(name, size, price, explain)
    }
}

Burger.kt

  • 버거 메뉴 정보를 가지고 있는 클래스로 AbstractMenu 추상 클래스의 속성과 함수를 상속 받아 사용한다.
  • displayInfo() 함수에서 버거 메뉴의 이름, 가격, 설명 정보의 문자열을 반환한다.

처음에는 displayInfo() 함수를 반환값이 없는 타입으로 만들고 안에서 문자열을 출력하였다. 해당 함수에서 당장 정보를 출력해주는 것보다 문자열을 반환하여 외부에서 문자열을 새로 조합하는 게 나을 것 같아 함수를 수정하게 되었다.

class Burger(id: Int, category: String, name: String, price: Int, explain: String) :
    AbstractMenu(id, category, name, price, explain) {
    override fun displayInfo(): String {
        return "%-10s | ₩ %4d | %s".format(name, price, explain)
    }
}

Fried.kt

  • 사이드 메뉴 정보를 가지고 있는 클래스로 AbstractMenu 추상 클래스의 속성과 함수를 상속 받아 사용한다.
  • displayInfo() 함수에서 사이드 메뉴의 이름, 가격, 설명, 사이즈 정보의 문자열을 반환한다.
class Fried(
    id: Int,
    category: String,
    name: String,
    price: Int,
    description: String,
    private val size: String
) :
    AbstractMenu(id, category, name, price, description) {
    override fun displayInfo(): String {
        return "%s - %-5s| ₩ %4d | %s".format(name, size, price, explain)
    }
}

Kiosk.kt

fun main() {
    val productManage = ProductManage()

    while (true) {
        productManage.displayMain()
        val input = readln()
        var select: Int
        if (input.isNumber()) {
            select = input.toInt()
        } else {
            continue
        }

        when (select) {
            0 -> {
                println("프로그램을 종료 합니다.")
                break
            }

            1 -> {
                println("\n[ Burger MENU ]")
                productManage.displayMenu("burger")

                while (true) {
                    val enter = readln()
                    var number: Int
                    if (enter.isNumber()) {
                        number = enter.toInt()
                    } else {
                        continue
                    }

                    if (number == 0) {
                        break
                    } else if (number < 0 || number > productManage.getMenuCount("burger")) {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                    } else {
                        val item = productManage.getSelectedItem("burger", number)
                        productManage.displayItem(item)
                        break
                    }
                }
            }

            2 -> {
                println("\n[ Fried MENU ]")
                productManage.displayMenu("fried")

                while (true) {
                    val enter = readln()
                    var number: Int
                    if (enter.isNumber()) {
                        number = enter.toInt()
                    } else {
                        continue
                    }

                    if (number == 0) {
                        break
                    } else if (number < 0 || number > productManage.getMenuCount("fried")) {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                    } else {
                        val item = productManage.getSelectedItem("fried", number)
                        productManage.displayItem(item)
                        break
                    }
                }
            }

            3 -> {
                println("\n[ Beverage MENU ]")
                productManage.displayMenu("beverage")

                while (true) {
                    val enter = readln()
                    var number: Int
                    if (enter.isNumber()) {
                        number = enter.toInt()
                    } else {
                        continue
                    }

                    if (number == 0) {
                        break
                    } else if (number < 0 || number > productManage.getMenuCount("beverage")) {
                        println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
                    } else {
                        val item = productManage.getSelectedItem("beverage", number)
                        productManage.displayItem(item)
                        break
                    }
                }
            }

            else -> {
                println("잘 못 된 번호를 입력했어요. 다시 입력해주세요.")
            }
        }
    }

}
  • 숫자만 입력 받기 위해 입력 된 값이 숫자인지 아닌지 판단하는 함수
fun String.isNumber(): Boolean {
    return try {
        this.toInt()
        true
    } catch (e: NumberFormatException) {
        println("잘 못 된 문자 타입을 입력했어요. 다시 입력해 주세요.")
        false
    }
}
profile
개발 공부 기록 🌱

0개의 댓글