[์ค์ํํธ ๋์์ธํจํด] ๋ฐ์ฝ๋ ์ดํฐ ํจํด(Decorator Pattern)
๋ฐ์ฝ๋ ์ดํฐ ํจํด(Decorator Pattern)
Decorator pattern attatches additional repsonsibilities to an object dynamically.
๋ฐ์ฝ๋ ์ดํฐ ํจํด์ด ๋ฌด์์ผ๊น์? ์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๋ ์ด๋ค ๊ฐ์ฒด์ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ณ (๋ฉ์๋ ํธ์ถ) ๊ทธ์ ๋ํ ์๋ต์ผ๋ก ์ด๋ค ๋์์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ฒ๋ฉ๋๋ค. ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฉ์๋์ ๋์์ ์ถ๊ฐํด ๋ฐํ์์ ํด๋น ๊ฐ์ฒด์ ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ๋ ์๋ก์ด ๊ธฐ๋ฅ์ ์ํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๊ฒ ํ๋ ํจํด์ ๋๋ค.
๋ฐํ์ ํ์์ ์๋ก์ด ๋์์ ์ถ๊ฐํ ์ ์๋๋ก ํ๊ธฐ ์ํด์ ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ๊ฐ์ฒด๋ฅผ ํ๋ฒ ๊ฐ์ธ๋ ๋ํผ ๊ฐ์ฒด๋ฅผ ๋๊ฒ ๋ฉ๋๋ค.
์ด๋ ๊ฒ์! Concrete ๊ฐ์ฒด๋ ์๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ค๋ ํ์ ์ด๊ณ , Wrapper๋ Concrete์ ๊ฐ์ ํ์ ์ด๋ฉด์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ๊ฐ์ฒด์ ๋๋ค. ํ์ง๋ง ์ธ๋ถ์์ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋๋ concrete๊ฐ ๊ฐ์ง ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ ์ฒ๋ผ ๋ณด์ด์ฃ .
๋ฌด์จ ๋ง์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ฃ ..? ์์ ์ ํจ๊ป ์ ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ด ์ ํ์ํ์ง ๋ค์ ๊ณ ๋ฏผํด๋ด ์๋ค.
์๋ธ์จ์ด ๊ตฌํํด๋ณด๊ธฐ
์ฌ๋ฌ๋ถ์ด ์๋์์น ๊ฐ๊ฒ์ธ ์๋ธ์จ์ด๋ฅผ ์ฝ๋๋ก ์ฎ๊ฒจ๋ณด๋ ค๊ณ ๋ ธ๋ ฅํด๋ณธ๋ค๊ณ ํด๋ณผ๊ฒ์. ๊ธฐ๋ณธ ๋ฉ๋ด๋ ์๊ฒ ์ง๋ง ์๋ธ์จ์ด์ ๋ฌ๋ฏธ๋ ์ํ๋ ์ฌ๋ฃ๋ฅผ ๋ง์๋๋ก ์์ด์ ๊ธ์ก์ ์ง๋ถํ๋ ๊ฒ์ด๊ฒ ์ฃ . ๊ทธ๋ผ ๋จผ์ ๊ธฐ๋ณธ์ ์ธ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ด ์๋ค.
import Foundation
protocol Sandwich: CustomStringConvertible {
func cost () -> Int
}
class OriginalSandwich: Sandwich {
var description: String {
return "OriginalSandwich"
}
func cost() -> Int {
return 3000
}
}
class VeganSandwich: Sandwich {
var description: String {
return "VeganSandwich"
}
func cost() -> Int {
return 2500
}
}
Sandwich ํ๋กํ ์ฝ์ ํ๋ ๋ง๋ค๊ณ , ๊ธฐ๋ณธ ์๋์์น์ ๋น๊ฑด ๊ธฐ๋ณธ ์๋์์น ํ์ ์ ๋ง๋ค์ด์ฃผ์์ด์. ์ง๊ธ์ ๋ ์ข ๋ฅ์ ์๋์์น๊ฐ ์๋๋ฐ์, ์๋ธ์จ์ด์์ ํ๋ฏ์ด ์ฌ๋ฃ๊ฐ ๋ ์ถ๊ฐ๋์ด์ ์ข ๋ฅ๊ฐ ๋ง์์ง๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
protocol Sandwich: CustomStringConvertible {
func cost () -> Int
}
class OriginalSandwich: Sandwich {
var description: String {
return "OriginalSandwich"
}
func cost() -> Int {
return 3000
}
}
class VeganSandwich: Sandwich {
var description: String {
return "VeganSandwich"
}
func cost() -> Int {
return 2500
}
}
class meatballSandwich: Sandwich {
var description: String {
return "meatballSandwich"
}
func cost() -> Int {
return 3500
}
}
class avocadoSandwich: Sandwich {
var description: String {
return "avocadoSandwich"
}
func cost() -> Int {
return 4500
}
}
๋จ์ผ ์ฑ ์ ์์น์ ์งํค๊ธฐ ์ํด์ ์ด๋ ๊ฒ ์๊ฒ ์ธ๋ถ ํ์ ์ ๋ ๋ง๋ค์ด์ฃผ๋ ๋ฐฉ๋ฒ๋ ์๊ฒ ์ง๋ง, ์ข ๋ฅ๊ฐ ๋ง์ผ๋ฉด ๋ง์์๋ก ํด๋์ค์ ๊ฐ์๊ฐ ๋์ด๋ฉ๋๋ค. ๋ชจ๋ ์กฐํฉ์ ๋ํด์ ์ ํด๋์ค๋ฅผ ๋ง๋ค ์๋ ์์ผ๋๊น์. ์ข์ ๋ฐฉ๋ฒ์ ์๋ ๊ฒ ๊ฐ์ฃ ?
๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ชจ๋ ์ฌ๋ฃ๋ฅผ ์ ์ํด๋๊ณ Boolean์ผ๋ก ์ฌ์ฉํ ์ฌ๋ฃ๋ฅผ ๋ฐ๊ฟ์ค ์๋ ์๊ฒ ์ฃ .
import Foundation
protocol Sandwich: CustomStringConvertible {
var hasAvocado: Bool { get set }
var hasMeatBall: Bool { get set }
func cost () -> Int
}
extension Sandwich {
mutating func toggleAvocado() {
self.hasAvocado.toggle()
}
mutating func toggleMeatBall() {
self.hasMeatBall.toggle()
}
}
class OriginalSandwich: Sandwich {
var hasAvocado: Bool
var hasMeatBall: Bool
var description: String {
return "OriginalSandwich"
}
init(hasAvocado: Bool, hasMeatBall: Bool) {
self.hasAvocado = hasAvocado
self.hasMeatBall = hasMeatBall
}
func cost() -> Int {
return 3000
}
}
class VeganSandwich: Sandwich {
var hasAvocado: Bool
var hasMeatBall: Bool
var description: String {
return "VeganSandwich"
}
init(hasAvocado: Bool, hasMeatBall: Bool) {
self.hasAvocado = hasAvocado
self.hasMeatBall = hasMeatBall
}
func cost() -> Int {
return 2500
}
}
ํ์ง๋ง ์ด ๋ฐฉ๋ฒ ์ญ์ ์กฐํฉํด์ผํ ์ฌ๋ฃ๊ฐ ์์ญ๊ฐ์ง๊ฐ ๋๋ค๋ฉด ์์ฑ์๊ฐ ๋๋ฌด ๋ณต์กํด์ง๊ณ , ๊ธ์ก์ ๊ณ์ฐํ ๋ ํ์ฐ์ ์ผ๋ก ๋ถ๊ธฐ์ฒ๋ฆฌ๋ฅผ ์งํํ๊ฒ ๋ฉ๋๋ค. ๋, ๋น๊ฑด ์๋์์น์ ๊ฒฝ์ฐ์๋ hasMeatBall์ด๋ผ๋ ๋ฉ์๋๋ฅผ ์ ๋ ์ฌ์ฉํ์ง ์๋๋ฐ๋, ์ธํฐํ์ด์ค์ ๋ฏธํธ๋ณผ์ด ์๋ค๋ ์ด์ ๋ก hasMeatBall์ด๋ผ๋ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ์ฆ, ์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น(ISP)์ ์๋ฐฐํ๊ฒ ๋์ฃ . ๊ฒฐ์ ์ ์ผ๋ก ์๋ก์ด ์ฌ๋ฃ๊ฐ ์ถ๊ฐ๋ ๋๋ง๋ค ๊ตฌ์ฒด ํ์ ๊ณผ ์ถ์ ํด๋์ค๋ฅผ ๋ชจ๋ ์์ ํด์ฃผ์ด์ผํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐฉ ํ์ ์์น(OCP)๋ฅผ ๋ฐ๋ฅด์ง ์๋ ๊ตฌ์กฐ์ ์ฝ๋๊ฐ ๋ฉ๋๋ค.
๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ์ด๋ฐ ์ํฉ์์ ์ ์ฐํ๊ฒ ์๋ก์ด ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํ๊ณ , ๋ฐํ์์๋ ๋์ ์ผ๋ก ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํด์ ๊ธฐ์กด ๊ฐ์ฒด์ ์ฝ๋๋ฅผ ์์ ํ์ง ์์ ์ฑ๋ก ์๋ก์ด ๊ธฐ๋ฅ์ด๋ ์ ๋ณด๋ฅผ ๊ฐ์ฒด์ ์ถ๊ฐํ ์ ์๊ฒ ํฉ๋๋ค.
๋ฐ์ฝ๋ ์ดํฐ ํจํด ์ ์ฉํ๊ธฐ
๊ทธ๋ผ ์ ์์ ์ ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ์ ์ฉํด์ ์ข ๋ ๋์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์.
๋จผ์ ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ์ ๋ฆฌํด๋ณด์ฃ . ๊ฐ์ฅ ์ต์์์ ์๋ Component๋ ์ฐ๋ฆฌ๊ฐ ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํ ๊ฐ์ฒด์ ์ถ์ํด๋์ค์ ๋๋ค. ์ฐ๋ฆฌ์ ์์ ์์๋ Sandwich๊ฐ ๋๊ฒ ์ฃ ? ๊ทธ๋ฆฌ๊ณ ์ด ์ถ์ํ๋ ํด๋์ค๋ฅผ ๊ตฌํํ๋ ๊ตฌํ์ฒด๊ฐ ConcreteComponent, ์ฆ ์ฐ๋ฆฌ์ ์์ ์์๋ OriginalSandwich์ VeganSandwich๊ฐ ๋ฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ด ๊ตฌ์ฒด ํ์ ์ Decorator๋ฅผ ํตํด ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํด์ฃผ๋ ค๊ณ ํด์. ์ด ์ฌ๋ฃ๊ฐ ๋ ํ์ ๋ค์ ์ถ์ ํด๋์ค๊ฐ Decorator์ ๋๋ค. ๊ทธ๋ฆผ์์ Decorator๊ฐ Component๋ฅผ ์์ํ๋ ๊ฒ๊ณผ ๋์์ Component๋ฅผ ์์ ํ๊ณ ์๋๋ฐ์, ์ด์ ์ ๋ํด์ ๊ณ ๋ฏผํด๋ด ์๋ค.
๋จผ์ , ์ฐ๋ฆฌ๊ฐ ๊ธ์ก์ ๊ณ์ฐํ๊ธฐ ์ํด cost ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค๊ณ ํด๋ณผ๊ฒ์, ๊ทธ๋ผ ๊ธฐ๋ณธ ํ์ (OriginalSandwich, VeganSandwich)์ Decorator๋ฅผ ํตํด ์ถ๊ฐํ ์ฌ๋ฃ๋ค์ ๊ฐ๊ฒฉ์ด ์ถ๊ฐ๋์ด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง๋ง ์ฐ๋ฆฌ๋ Sandwich ํ์ ์ ๋ฐ๋ก ์ฌ๋ฃ์ ๋ํ ๋ชฉ๋ก์ ๊ฐ์ง๊ณ ์์ง๋ ์์์. ๋จ์ผ ์ฑ ์ ์์น๊ณผ ๊ฐ๋ฐฉ ํ์ ์์น์ ์งํค๊ธฐ ์ํด์์.
๊ทธ๋์ Decorator์ ๊ฐ ํ์ ๋ค์ Sandwich ํ์ ์ ์์ ํ๊ณ , ๋์์ Sandwich์์ ๊ฐ์ ํ๋ ๋ฉ์๋๋ค์ ๊ตฌํํด์ ์ฌ๊ท์ ์ผ๋ก ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋๋ก ํด์ผํฉ๋๋ค.
๋ฐ๋ผ์ ๊ธ์ก์ ์ป๊ธฐ ์ํ ๋ก์ง์ ๋ฐ๋ผ์ ์ด๋ ๊ฒ ๋๊ฒ ์ฃ . ๋ฉ์๋ ์์ฒญ์ด ๋ค์ด๊ฐ๋ฉด ๊ฐ์ฅ ์ค์ฌ์ ์๋ ConcreteComponent๊น์ง ๋๋ฌํ๊ณ , ์ด๋ฅผ base case๋ก ์ผ์์ ๊ฐ ์ฌ๋ฃ์ ๊ฐ๊ฒฉ๋ค์ ๋ํด ์ต์ข ์ ์ธ ๊ธ์ก์ ๊ตฌํ๊ฒ ๋๋ ๊ฒ์ ๋๋ค. ์ด๋ฐ ๋ฐฉ์์ผ๋ก ๊ตฌ์ฑํ๋ค๋ฉด ๊ฐ ์ฌ๋ฃ๋ค์ ๋ค๋ฅธ ์ฌ๋ฃ๋ค์ ์ํฉ์ ์ ๊ฒฝ์ธ ํ์๋ ์๊ณ , Concrete Component๋ ์์ ์๊ฒ ์ด๋ค ์ฌ๋ฃ๊ฐ ์ถ๊ฐ๋๋์ง ์ ํ์๊ฐ ์์ด์ง๋๋ค.
๊ทธ๋ผ ๊ตฌํํด๋ณผ๊น์?
๋ฐ์ฝ๋ ์ดํฐ ํจํด ๊ตฌํํ๊ธฐ
๋จผ์ ๊ธฐ๋ฅ๋ค์ ์ถ๊ฐํ ์ ์๋๋ก ํด์ฃผ๋ ๋ฐ์ฝ๋ ์ดํฐ๋ถํฐ ๋ง๋ค์ด๋ด ์๋ค.
protocol Decorating: Sandwich {
var sandwich: Sandwich { get set }
}
๋ฐ์ฝ๋ ์ดํฐ ํ๋กํ ์ฝ์ ๋ง๋ค์๊ณ , ๋ด๋ถ์๋ Sandwich ํ์ ์ ๋ณ์๋ฅผ ๊ฐ์ง๋๋ก ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ฑํ์ด์. ๋ฐ์ฝ๋ ์ดํฐ ํ๋กํ ์ฝ์ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ ์ฉํ ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด์ ํ์ ์ ์์ํ๊ฑฐ๋ ์ฑํํด์ผํ๊ณ , ๋์์ ๊ฐ์ ํ์ ์ ์ธ์คํด์ค๋ฅผ ๋ฉค๋ฒ๋ก ๊ฐ์ง๊ณ ์์ด์ผ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ํ๋กํ ์ฝ์ ์ฑํํ๋ ์ฌ๋ฃ์ ์ญํ ์ ํ Concrete Decorator๋ ์๋ณด์นด๋์ ๋ฏธํธ๋ณผ์ด ๋๊ฒ ์ฃ .
class Avocado: Decorating {
var sandwich: Sandwich
var description: String {
return self.sandwich.description + " + Avocado"
}
init(sandwich: Sandwich) {
self.sandwich = sandwich
}
func cost() -> Int {
return self.sandwich.cost() + 1000
}
}
class MeatBall: Decorating {
var sandwich: Sandwich
var description: String {
return self.sandwich.description + " + MeatBall"
}
init(sandwich: Sandwich) {
self.sandwich = sandwich
}
func cost() -> Int {
return self.sandwich.cost() + 1500
}
}
๊ฐ ์ฌ๋ฃ๋ค์ ์์ฑ์๋ก Sandwich ํ์ ์ ๋ฐ์์. ํ์ง๋ง ์ด ํ์ ์ ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํ ๋์์ธ Concrete Component ๋ฟ๋ง ์๋๋ผ, Decorator๋ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ Decorator๋ฅผ ์์ฑ์๋ก ์ ๋ฌํ๋ ๊ฒ๋ ๊ฐ๋ฅํ์ฃ . ์ ์ด๋ ๊ฒ ํ๋์ง ์ ์ดํด๊ฐ ์๋์ด๋ ๊ด์ฐฎ์์..! ์ ์ ํ์ ์์ฑ์๋ฅผ ์ฌ์ฉํด๋ณด๋ฉด ๋ช ์พํด์ง๋๋ค!
๊ฐ ์ฌ๋ฃ๋ค์ด ๊ตฌํํ๋ ๋ฉ์๋์ ์ฐ์ฐ ํ๋กํผํฐ๋ ์์ฑ์๋ก ๋ฐ์ Sandwich ํ์ ์ด ๊ฐ์ง ๋๋ช ์ ๋ฉ์๋/์ฐ์ฐ ํ๋กํผํฐ๋ฅผ ํธ์ถํ๊ณ ๊ทธ ๋ฐํ ๊ฐ์ ์์ ์ ์ํ ๊ฐ์ ์ถ๊ฐํด์ฃผ๋ ๋ฐฉ์์ ๋๋ค.
๊ฐ์ ์ถ์ ํด๋์ค๋ฅผ ๊ตฌํํ๊ณ ์์ง๋ง, ๊ฐ์ฅ ๊ธฐ๋ณธ ํ์ ์ด ๋ Concrete Component๋ ์กฐ๊ธ ๋ค๋ฅด๊ฒ ๊ตฌํ์ ํฉ๋๋ค.
class OriginalSandwich: Sandwich {
var description: String {
return "OriginalSandwich"
}
func cost() -> Int {
return 3000
}
}
class VeganSandwich: Sandwich {
var description: String {
return "VeganSandwich"
}
func cost() -> Int {
return 2500
}
}
์ฌ๊ท๋ฅผ ์ข ๋ฃํ base case๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ด์์. Concrete Component์ ๊ฒฝ์ฐ์๋ ์์ ์ ๊ฐ๋ง ๋ฐํํ๊ณ ์ข ๋ฃ๋ฉ๋๋ค. ์ฌ๊ธฐ์ ๋ฐํ๋๋ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ฌ๋ฃ๋ค์ด ๊ฐ์ง ๋ฉ์๋์์ ๊ฐ ์ฌ๋ฃ๋ค์ ๊ฐ์ด ์ถ๊ฐ๋์ด์ ์ฒ๋ฆฌ๋๋ ๊ฒ์ด์ฃ .
์ด์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด๋ด ์๋ค!
let avocadoMeatBallSandwich = MeatBall(sandwich: Avocado(sandwich: OriginalSandwich()))
print(avocadoMeatBallSandwich.cost())
print(avocadoMeatBallSandwich)
์๊น Sandwich ํ์ ์ Decorator๊ฐ ๋ฐ๋ฅด๊ณ ์์์ฃ ? ๊ทธ ์ด์ ๋ ์๋ก์ด ์ฌ๋ฃ๊ฐ ์ถ๊ฐ๋ Concrete Component๋ฅผ ์์ฑ์์ ๋ฃ์ด์ฃผ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋๋ก ํ๊ธฐ ์ํด์์ ๋๋ค. ์ด๋ ๊ฒ ํ ์ ์๋ค๋ฉด ๋ฐ์ฝ๋ ์ดํฐ๋ ์ธ์คํด์ค๋ง๋ค ๋ฑ ํ๋๋ง ์ถ๊ฐํ ์ ์์๊ฑฐ์์.
์์๋๋ก ๋ฏธํธ๋ณผ, ์๋ณด์นด๋ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ ๋ง์ง๋ง์ Concrete Component์ ์ธ์คํด์ค๋ฅผ ์ฃผ๋ฉด,
์ด ๊ทธ๋ฆผ์ด ๊ทธ๋๋ก ๊ตฌํ์ด ๋ฉ๋๋ค.
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ ์ฐ๋ฆฌ๊ฐ ์๋ํ๋๋ก์์ด์.
์๋ก์ด ์ฌ๋ฃ์ ๋ฑ์ฅ
๋ง์ฝ ๋ฐํ์์ "ํ ๋งํ " ๋ผ๋ ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํด์ฃผ์ด์ผ ํ๋ ์ํฉ์ด ์๊ฒผ๋ค๋ฉด ์ด๋จ๊น์? ์ด๋ฐ ์ํฉ์์ ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ๋ฉ๋๋ค.
๋จผ์ Decorator ํ๋กํ ์ฝ์ ์ฑํํ๋ ํ ๋งํ ํ์ ์ ๋ง๋ค๊ฒ ์ต๋๋ค.
class Tomato: Decorating {
var sandwich: Sandwich
var description: String {
return self.sandwich.description + " + Tomato"
}
init(sandwich: Sandwich) {
self.sandwich = sandwich
}
func cost() -> Int {
return self.sandwich.cost() + 500
}
}
๊ฐ๋จํ๊ฒ ์ถ๊ฐ๊ฐ ๊ฐ๋ฅํ๊ฒ ์ฃ ? ๊ทธ๋ฆฌ๊ณ ๊ธฐ์กด์ ๋ง๋ค์๋ ๋ฏธํธ๋ณผ ์๋ณด์นด๋ ์๋์์น์ ํ ๋งํ ๋ฅผ ๋ฃ์ด์ค๋๋ค.
let tomatoAdded = Tomato(sandwich: avocadoMeatBallSandwich)
print(tomatoAdded.cost())
print(tomatoAdded)
๊ธฐ์กด ๊ฐ์ฒด๋ ๊ทธ๋๋ก ๋ ์ฑ๋ก ํ ๋งํ ๋ฅผ ์ถ๊ฐํ ๊ฐ์ฒด๋ฅผ ์์ฝ๊ฒ ๋ง๋ค์ด๋ผ ์ ์์ต๋๋ค. ์๋ก์ด ์ฌ๋ฃ๊ฐ ์์ฃผ ์ถ๊ฐ๋๊ฑฐ๋, ๋์ ์ผ๋ก ๊ธฐ์กด ๊ฐ์ฒด์ ์๋ก์ด ์ํ๋ฅผ ๋ง๋ค์ด๋ด๊ณ ์ถ๋ค๋ฉด, ๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ์ฌ์ฉํด OCP๋ฅผ ๋ฐ๋ฅด๋ฉด์๋ ์ ์ฐํ๊ฒ ๋ณ๊ฒฝ์ ๋์ฒํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
์ค๋๋ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
'๐ฎ ์จ-์์ค > ๐ ๋์์ธํจํด' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote