프로토콜을 이용하여 클래스 혹은 구조체로 채택하여 if문, switch문 guard문을 반복적으로 사용하지 않고 프로그래밍을 할 수 있다.
이런 프로그래밍을 절차지향이라고 하는데 절차 지향으로 프로그래밍을 하다보면 코드가 복잡해지고 유지보수가 힘들게 코드가 꼬일수있다.
그래서 이번에 사용해본 객체지향 프로그래밍인데 프로토콜을 사용하여 구조체,클래스에 채택하여 간결하고 보수가 쉽게 만들 수 있었다.
아래 메뉴판을 보시고 메뉴를 골라 입력해주세요.
[ SHAKESHACK MENU ]
1. Burgers | 앵거스 비프 통살을 다져만든 버거
2. Frozen Custard | 매장에서 신선하게 만드는 아이스크림
3. Drinks | 매장에서 직접 만드는 음료
4. Beer | 뉴욕 브루클린 브루어리에서 양조한 맥주
0. 종료 | 프로그램 종료
1 <-
[ Burgers MENU ]
1. ShackBurger | W 6.9 | 토마토, 양상추, 쉑소스가 토핑된 치즈버거
2. SmokeShack | W 8.9 | 베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거
3. Shroom Burger | W 9.4 | 몬스터 치즈와 체다 치즈로 속을 채운 베지테리안 버거
3. Cheeseburger | W 6.9 | 포테이토 번과 비프패티, 치즈가 토핑된 치즈버거
4. Hamburger | W 5.4 | 비프패티를 기반으로 야채가 들어간 기본버거
0. 뒤로가기 | 뒤로가기
0 <-
[ SHAKESHACK MENU ]
1. Burgers | 앵거스 비프 통살을 다져만든 버거
2. Forzen Custard | 매장에서 신선하게 만드는 아이스크림
3. Drinks | 매장에서 직접 만드는 음료
4. Beer | 뉴욕 브루클린 브루어리에서 양조한 맥주
0. 종료 | 프로그램 종료
0 <-
프로그램을 종료합니다.
위와 같은 프로그래밍을 구현하기 위해 처음 생각한 방법은 조건 문안에 조건문을 사용하여 구현하는 방식이었지만 아래와 같은 코드를 사용하니 코드가 간결해진 것을 확인할 수 있다.
/// main.swift
import Foundation
let app = App.shared
let io: IOInterface = TerminalInterface.shared
app.register(option: BurgerMenu())
app.register(option: FrozenCustardMenu())
app.register(option: DrinkMenu())
app.register(option: BeerMenu())
app.run(io: io)
/// app.swift
import Foundation
class App {
static let shared = App()
let io = TerminalInterface.shared
// BurgerMenu(), FrozenCustardMenu(), DrinkMenu(), BeerMenu()
var options: [Option] = []
func register(option: Option) { options.append(option) }
func run(
io: IOInterface
) { while true {
let option = chooseService(io: io)
option.info()
}}
private func chooseService(io: IOInterface) -> Option {
io.output("[ SHAKESHACK MENU ]")
for i in options {
io.output(i.info())
}
io.output("-------------------")
let input = io.input("-> ", validate: {
guard let value = Int($0) else { return false }
return Int($0) != nil && (value > 0 && value <= self.options.count)
})
return options[Int(input)!]
}
private init() {}
}
/// menu.swift
import Foundation
protocol IOInterface {
func output(_ message: String)
func input(_ prompt: String, validate: ((String) -> Bool)?) -> String
func wait()
}
extension IOInterface {
func input(_ prompt: String) -> String {
return input(prompt, validate: nil)
}
}
class TerminalInterface: IOInterface {
static let shared: TerminalInterface = .init()
func output(_ message: String) {
print(message)
}
func input(_ prompt: String, validate: ((String) -> Bool)? = nil) -> String {
while true {
print(prompt, terminator: "")
guard let input = readLine() else { exit(1) }
guard input.count > 0 else { continue }
if validate?(input) != false {
return input
}
}
}
func wait() {
_ = readLine()
}
private init() {}
}
protocol Option {
var id: Int { get }
var name: String { get }
var desc: String { get }
func info() -> String
}
protocol Menu {
var price: Int { get }
}
extension Option {
func info() -> String {
return "\(id). \(name)\t\t\t | \(desc)"
}
}
protocol MenuOption: Option, Menu {}
extension MenuOption {
func info() -> String {
let price = String(format: "%.1f", self.price / 1000)
return "\(id). \(name)\t\t\t | W \(price) | \(desc)"
}
}
protocol Burger: MenuOption {}
protocol FrozenCustard: MenuOption {}
protocol Drink: MenuOption {}
protocol Beer: MenuOption {}
struct BurgerMenu: Option { var id: Int { 1 }
var name: String { "Burger" }
var desc: String { "맛있는 버거" }
}
struct ShackBurgerMenu: Burger {
var id: Int { 1 }
var name: String { "ShackBurger" }
var desc: String { "토마토, 양상추, 쉑소스가 토핑된 치즈버거" }
var price: Int { 6900 }
}
struct ShroomBurger: Burger {
var id: Int { 2 }
var name: String { "ShroomBurger" }
var desc: String { "몬스터 치즈와 체다 치즈로 속을 채운 베지테리안 버거" }
var price: Int { 9400 }
}
struct SmokeShack: Burger {
var id: Int { 3 }
var name: String { "SmokeShack" }
var desc: String { "베이컨, 체리 페퍼에 쉑소스가 토핑된 치즈버거" }
var price: Int { 8900 }
}
struct Cola: Drink {
var id: Int { 1 }
var name: String { "Cola" }
var desc: String { "코카콜라" }
var price: Int { 2500 }
}
struct Cider: Drink {
var id: Int { 2 }
var name: String { "Cider" }
var desc: String { "사이다" }
var price: Int { 2500 }
}
struct FrozenCustardMenu: Option { var id: Int { 2 }
var name: String { "FrozenCustard" }
var desc: String { "맛있는 아이스크림" }
}
struct DrinkMenu: Option { var id: Int { 3 }
var name: String { "Drink" }
var desc: String { "맛있는 음료" }
}
struct BeerMenu: Option { var id: Int { 4 }
var name: String { "ShackBurger" }
var desc: String { "맛있는 맥주" }
}
struct VanilaFrozenCustard: FrozenCustard {
var id: Int { 1 }
var name: String { "Vanila Frozen Custard" }
var desc: String { "바닐라맛 Vanila Frozen Custard" }
var price: Int { 5500 }
}
struct ChocolateFrozenCustard: FrozenCustard {
var id: Int { 2 }
var name: String { "Chocolate Frozen Custard" }
var desc: String { "초콜릿맛 Chocolate Frozen Custard" }
var price: Int { 5500 }
}
struct Lager: Beer {
var id: Int { 1 }
var name: String { "Lager" }
var desc: String { "브루클린 라거" }
var price: Int { 4500 }
}
struct BrownAle: Beer {
var id: Int { 1 }
var name: String { "BrownAle" }
var desc: String { "상큼한 브라운 에일" }
var price: Int { 4500 }
}
(위 코드들은 아직 첫 번째 메뉴와 입력만 받을 수 있는 코드이다.)
'Today I Learned' 카테고리의 다른 글
단일책임원칙_Single Responsibilty Principle(SOLID 5원칙 중 한가지) - TIL (0) | 2023.07.27 |
---|---|
SOLID 5원칙(객체지향 설계원칙)_TIL (0) | 2023.07.26 |
23년 7월 24일 TIL (0) | 2023.07.24 |
23년 7월 21일 TIL (0) | 2023.07.21 |
23년 7월 20일 TIL (0) | 2023.07.20 |