250x250
Rainbow๐ŸŒˆCoder
My dev Note๐Ÿ“’
Rainbow๐ŸŒˆCoder
์ „์ฒด ๋ฐฉ๋ฌธ์ž
์˜ค๋Š˜
์–ด์ œ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (411)
    • ๊ณต์ง€์‚ฌํ•ญ (0)
    • Debugger (10)
      • Visual Studio Debugger (1)
      • Chrome DevTools (3)
      • Visual Studio Code Debugger (4)
      • eclipse (1)
      • intelliJ (1)
    • OOP (2)
      • OOP (2)
    • TypeScript (54)
      • ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ TypeScript (54)
    • Javascript (87)
      • Javascript (45)
      • Node.js (19)
      • React (5)
      • FE ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ค์ • (3)
      • React์™€ Node ๊ฐ™์ด ๋•Œ๋ ค์žก๊ธฐ (6)
      • next.js (2)
      • pixi.js (7)
    • ๋งˆํฌ์—… (23)
      • Html & Css (23)
    • C# (80)
      • C# (12)
      • ์ด๊ฒƒ์ด C#์ด๋‹ค (68)
    • C++ (30)
      • c++ (27)
      • win api (3)
    • Unity (18)
      • Unity(๊ธฐ์ดˆ) (8)
      • Unity(C#์ค‘๊ธ‰) (5)
      • ์œ ๋‹ˆํ‹ฐ ํฌํ†ค(๋„คํŠธ์›Œํฌ) (4)
      • unity c# MyCode (1)
    • Java & Spring (29)
      • Java (11)
      • ์Šคํ”„๋ง (8)
      • Java Algorithm (9)
      • Javs Data Structures (1)
    • ์ž๋ฃŒ๊ตฌ์กฐ์™€ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (15)
      • ์ž๋ฃŒ๊ตฌ์กฐ (5)
      • ์•Œ๊ณ ๋ฆฌ์ฆ˜ (10)
    • ํ˜•์ƒ๊ด€๋ฆฌ (15)
      • Git (11)
      • ์†Œ์ŠคํŠธ๋ฆฌ (3)
    • ๊ทธ๋ž˜ํ”ฝ์Šค (7)
      • WebGl (7)
    • AWS (3)
      • aws (3)
    • ๋ฆฌ๋ˆ…์Šค (5)
      • ๋ฆฌ๋ˆ…์Šค (5)
    • ์ฑ… ๋ฆฌ๋ทฐ (13)
      • ํด๋ฆฐ์ฝ”๋“œ(์ฑ…๋ฆฌ๋ทฐ) (3)
      • ์œ ์ง€๋ณด์ˆ˜๊ฐ€๋Šฅํ•œ์ฝ”๋”ฉ์˜๊ธฐ์ˆ C#ํŽธ(์ฑ…๋ฆฌ๋ทฐ) (1)
      • ๋ฆฌํŒฉํ† ๋ง(์ž๋ฐ”์Šคํฌ๋ฆฝํŠธํŒ) (9)
    • Server (2)
      • ๊ฒŒ์ž„ ์„œ๋ฒ„(๋„คํŠธ์›Œํฌ, ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ,OS) (2)
    • ์„ค๊ณ„, ์•„ํ‚คํ…์ณ (4)
    • ํŒŒ์ด์ฌ (5)
    • ๋””์ž์ธํŒจํ„ด (2)
    • mocha (2)
    • Jest (1)
    • Spine (1)
    • ์ธ๊ณต์ง€๋Šฅ (1)
      • ํ˜ผ์ž๊ณต๋ถ€ํ•˜๋Š”๋จธ์‹ ๋Ÿฌ๋‹+๋”ฅ๋Ÿฌ๋‹ (1)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ํƒœ๊ทธ
  • ๋ฐฉ๋ช…๋ก

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

ํƒœ๊ทธ

  • ์œ„์ž„
  • ์ปดํฌ์ง€์…˜
  • ใ…ฃใ„ท
  • MySQL

์ตœ๊ทผ ๋Œ“๊ธ€

์ตœ๊ทผ ๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

hELLO ยท Designed By ์ •์ƒ์šฐ.
Rainbow๐ŸŒˆCoder

My dev Note๐Ÿ“’

[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] ๊ฐ์ฒด์ง€ํ–ฅ์˜ ๊ฝƒ composition(๋ถ€์ œ: ์ƒ์†์˜ ๋ฌธ์ œ์ )
TypeScript/ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ TypeScript

[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] ๊ฐ์ฒด์ง€ํ–ฅ์˜ ๊ฝƒ composition(๋ถ€์ œ: ์ƒ์†์˜ ๋ฌธ์ œ์ )

2022. 4. 22. 19:03
728x90

 

 

 Favor Composition over inheritance 

 

"์ƒ์† ๋Œ€์‹ ์— ์ปดํฌ์ง€์…˜(๋œป: ๊ตฌ์„ฑ์š”์†Œ๋“ค, ๊ตฌ์„ฑ)์„ ๋” ์„ ํ˜ธํ•˜์„ธ์š”."

 

 

 

 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ OOP์˜ ๊ฝƒ, composition์„ ๋‹ค๋ฃจ๊ธฐ ์ „์— ์ƒ์†์˜ ๋ฌธ์ œ์ ์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์•Œ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

๋ฏธ๋ฆฌ ๋งํ•˜์ž๋ฉด, composition์€ ๋ณต์žกํ•˜๊ฒŒ ์ƒ์†์˜ ์ˆ˜์ง ๊ตฌ์กฐ๊ฐ€ ๊ธธ์–ด์ง€๋Š” ๋Œ€์‹ ์— ์ƒ์†์˜ ๋ ˆ๋ฒจ์„ ํ•œ ๋‹จ๊ณ„๋กœ๋งŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

๋ฌธ์ œ์ ๋„ ๋ฏธ๋ฆฌ ๋งํ•˜์ž๋ฉด, composition์šฉ์œผ๋กœ ๊ฐ€์ ธ๋‹ค ์“ฐ๋Š” ํด๋ž˜์Šค์™€ ๊ฐ€์ ธ์˜ค๋Š” ํด๋ž˜์Šค ์‚ฌ์ด์˜ ์ปคํ”Œ๋ง์ด ๋„ˆ๋ฌด ์‹ฌํ•˜๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค.( ๊ฐ€์ ธ๋‹ค ์“ฐ๋Š” ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋กœ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด, ๊ฐ€์ ธ๋‹ค ์“ฐ๋Š” ํด๋ž˜์Šค์™€ ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ํด๋ž˜์Šค์— ๋“ค์–ด๊ฐ€์„œ ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•œ๋‹ค.-> ๋” ํ™•์žฅ์ด ์‰ฝ๊ณ  ์œ ์—ฐํ•œ ํ…Œํฌ๋‹‰์€ ๋‹ค์Œ ํฌ์ŠคํŒ…์„ ๋ณด๋ฉด๋œ๋‹ค(๊ฐ•๋ ฅํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•œ ์ „๋žตํŒจํ„ด))

 

<์ƒ์†์˜ ๋ฌธ์ œ์ >

์กฑ๋ณด๊ฐ€ ๊ผฌ์ธ๋‹ค...

์ƒ์†์˜ ๊นŠ์ด๊ฐ€ ๋„ˆ๋ฌด ๊นŠ์–ด์ ธ์„œ ์กฐ์ง๋„๊ฐ€ ์ปค์ง€๋‹ค๋ณด๋ฉด ๊ด€๊ณ„์„ฑ์ด ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

 

 

์ปคํ”ผ๋จธ์‹ ์„ ์ƒ์†๋ฐ›์€ ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ ๊ณผ ์†Œ๊ธˆ์ปคํ”ผ๋จธ์‹ ์ด ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์†Œ๊ธˆ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ ์ด ํ•„์š”ํ•ด์ง€๋ฉด? 

(๋‹คํ–‰์Šค๋Ÿฝ๊ฒŒ๋„) ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์ฃฝ์Œ์˜ ๋‹ค์ด์•„๋ชฌ๋“œ ์ƒ์† ๊ตฌ์กฐ๋ฅผ ๋ง‰๊ณ  ์žˆ๋‹ค.

 

์œ„์™€ ๊ฐ™์€ ์ฃฝ์Œ์˜ ๋‹ค์ด์•„๋ชฌ๋“œ ์ƒ์†๊ตฌ์กฐ๊ฐ€ ๋ง‰ํžŒ ์ด์œ ๋Š” ๋ณธ ํฌ์ŠคํŒ… ์ฐธ๊ณ (https://rainbowcode.tistory.com/174)(c#์˜ˆ์ œ์ด๊ธด ํ•˜๋‚˜, ์–ด์ฐจํ”ผ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ์ฃผ์ถ•์ด C#๊ฐœ๋ฐœ์ฃผ์ถ•์ด๋ผ์„œ OOP ์–ธ์–ด ์ฒ ํ•™์ด ์ƒ๋‹นํžˆ ์œ ์‚ฌ๋‹ค๊ณ  ๋ณด๋ฉด ๋˜๋ฏ€๋กœ, ๋…ํ•ด์— ์–ด๋ ค์›€์€ ์—†์„ ๊ฒƒ์ด๋‹ค. 

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ

์œ„ํ‚ค๋ฐฑ๊ณผ
๋ฉ€ํ‹ฐ ํŒจ๋Ÿฌ๋‹ค์ž„: ํ•จ์ˆ˜ํ˜•, ์ œ๋„ค๋ฆญ, ๋ช…๋ นํ˜•, ๊ฐ์ฒด ์ง€ํ–ฅ

๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ
๋• ํƒ€์ดํ•‘, gradual, structural[4]
์•„ํŒŒ์น˜ ๋ผ์ด์„ ์Šค 2.0
.ts, .tsx
www.typescriptlang.org

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ(TypeScript)๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์Šˆํผ์…‹์ธ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๋‹ค. ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ์—์„œ ๊ฐœ๋ฐœ, ์œ ์ง€ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์—„๊ฒฉํ•œ ๋ฌธ๋ฒ•์„ ์ง€์›ํ•œ๋‹ค. C#์˜ ๋ฆฌ๋“œ ์•„ํ‚คํ…ํŠธ์ด์ž ๋ธํŒŒ์ด, ํ„ฐ๋ณด ํŒŒ์Šค์นผ์˜ ์ฐฝ์‹œ์ž์ธ Anders Hejlsberg๊ฐ€ ๊ฐœ๋ฐœ์— ์ฐธ์—ฌํ•œ๋‹ค.[5] ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์™€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ๋ฅผ ์œ„ํ•œ ๊ฐœ๋ฐœ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ปค๋‹ค๋ž€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๊ณ„๋œ ์–ธ์–ด์ด๋‹ค.[6] ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์Šˆํผ์…‹์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์ด ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ๋„ ๋™์ž‘ํ•œ๋‹ค.

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ์ž์‹ ์ด ์›ํ•˜๋Š” ํƒ€์ž…์„ ์ •์˜ํ•˜๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ปดํŒŒ์ผ๋˜์–ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ๋ชจ๋“  ์šด์˜ ์ฒด์ œ, ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €, ๋ชจ๋“  ํ˜ธ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์˜คํ”ˆ ์†Œ์Šค์ด๋‹ค.

)

 

๊ฐ์„คํ•˜๊ณ   

์ด์ œ ์ปคํ”ผ๊ฐ€ ์ ์  ๋” ๋งŽ์•„์ง€๋ฉด?

ํ”„๋ ˆ์ฒผ ์ปคํ”ผ๋„ ์ƒˆ๋กœ ์„ ๋ณด์˜€๋Š”๋ฐ ๋ฐ˜์‘์ด ์ข‹์•„์„œ

์šฐ์œ ๊ฐ€ ๋“ค์–ด๊ฐ„ ํ”„๋ ˆ์ฒผ ์ปคํ”ผ๋„ ๊ฐœ๋ฐœํ•˜๊ณ  ๋˜ ๋ฐ˜์‘์ด ํ„ฐ์ ธ์„œ

์šฐ์œ ๊ฐ€ ๋“ค์–ด๊ฐ„ ํ”„๋ ˆ์ฒผ ์ปคํ”ผ์— ์†Œ๊ธˆ๋„ ๋ฟŒ๋ ค์„œ ํŒ๋งคํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

๊ณ„์† ์•„๋ž˜๋กœ ์ƒ์†์‹œ์ผœ์ค˜์•ผ ํ• ๊นŒ? ๊ทธ๋ž˜์„œ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ๋จธ์‹ ๋“ค ๋•Œ๋ฌธ์— ์กฑ๋ณด๊ฐ€ ๋์—†์ด ๊ธธ์–ด์ ธ์„œ ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐ€๊ฒŒ ๋ ๊นŒ?

๋ณธ๊ฒฉ์ ์œผ๋กœ ์กฑ๋ณด๊ฐ€ ๊ผฌ์ด๊ฒŒ ๋œ๋‹ค.

์ƒ์†์ด ๋ฌธ์ œ๋ผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ์ƒ์†์œผ๋กœ ํ’€๋ ค๊ณ  ํ•˜๋ฉด ๊ผฌ์ธ๋‹ค๋Š” ๋œป์ด๋‹ค.

(์ƒ์†์€ ์ฝ”๋“œ ์ค‘๋ณต์„ ์—†์•ฐ๊ณผ ๋™์‹œ์— ๋‹คํ˜•์„ฑ ๊ตฌํ˜„์„ ์œ„ํ•œ ํ•„์ˆ˜์š”์†Œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค)

 

 

ํŠนํžˆ๋‚˜ ์ƒ์†์€ ์œ„์—์„œ ์•„๋ž˜๋กœ ์ˆ˜์ง์ ์œผ๋กœ ๊ด€๊ณ„๊ฐ€ ํ˜•์„ฑ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ์ƒ์†์˜ ์น˜๋ช…์ ์ธ ๋ฌธ์ œ์ ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์–ด๋–ค ๋ถ€๋ชจํด๋ž˜์Šค์˜ ํ–‰๋™์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋˜๋ฉด 

์ด ์ˆ˜์ •๋œ ์‚ฌํ•ญ๋•Œ๋ฌธ์— ์ƒ์†๋ฐ›๋Š” ๋ชจ~๋“  ์ž์‹ ํด๋ž˜์Šค๋“ค์ด ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜๋ฐ–์— ์—†๋Š” ๊ตฌ์กฐ์ด๋‹ค.

(์œ„์—์„œ ๋ฌธ์ œ๊ฐ€ ํ„ฐ์ ธ์„œ ์†๋ณด๋ฉด ์•„๋ž˜๋„ ํ„ฐ์ ธ์„œ ์ผ์ผํžˆ ์ฐพ์•„๊ฐ€์„œ ๊ณ ์ณ์ค˜์•ผ ํ•˜๋Š” ๊ตฌ์กฐ)

 

์ด๋Ÿฌํ•œ ์ƒ์†์˜ ๋ฌธ์ œ์ ๋“ค ๋•Œ๋ฌธ์— ์ƒ์†์ด ๋ถˆํ•„์š”ํ•ด์ง€๋Š” ์„ ์ด ์˜ค๋ฉด, ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹๋‹ค!

 

 

 

 

<๋ชจ๋“  ๊ฒƒ์„ ๋’ค์—Ž๋Š” ์ปดํฌ์ง€์…˜, Favor Composition over inheritance>

 

 Favor Composition over inheritance 

"์ƒ์† ๋Œ€์‹ ์— ์ปดํฌ์ง€์…˜(๋œป: ๊ตฌ์„ฑ์š”์†Œ๋“ค, ๊ตฌ์„ฑ)์„ ๋” ์„ ํ˜ธํ•˜์„ธ์š”."

 

๋ ˆ๊ณ ์„ฑ์„ ์Œ“์„ ๋•Œ๋งˆ๋‹ค ํ•„์š”ํ•œ ๋ถ€ํ’ˆ๋“ค์„ ํ•˜๋‚˜์”ฉ ๊ฝ‚์•„์„œ ์กฐ๋ฆฝํ•ด๋‚˜๊ฐ€๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ์ปดํฌ์ง€์…˜๋„ ํ•˜๋‚˜์”ฉ ๊ฝ‚์•„๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

์ปดํฌ์ง€์…˜์„ ํ†ตํ•ด ์†Œ๊ธˆ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ ์„ ๋งŒ๋“ค์–ด๋ณธ๋‹ค.

 

์ด๋Ÿฌํ•œ ์ปดํฌ์ง€์…˜์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ• ๊นŒ 

 

 

์•„๋ž˜ ์†Œ์Šค์ฝ”๋“œ(์ปคํ”ผ๋จธ์‹ , ์ปคํ”ผ๋จธ์‹ ์„ ์ƒ์†ํ•œ ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ , ์ปคํ”ผ๋จธ์‹ ์„ ์ƒ์†ํ•œ ์†Œ๊ธˆ์ปคํ”ผ๋จธ์‹  ๊ตฌํ˜„๋˜์–ด์žˆ์Œ)์—

์†Œ๊ธˆ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ (๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์ปคํ”ผ๋„ ๋‚ด๋ ค์•ผํ•˜๊ณ , ๋ฐ์šด ์šฐ์œ ๋„ ํ•„์š”ํ•˜๊ณ , ์†Œ๊ธˆ๋„ ํ•œ๊ผฌ์ง‘ ๋„ฃ์€...) ์„ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

//   //์ปคํ”ผ๋จธ์‹  ๋งŒ๋“ค๊ธฐ
type CoffeeCup = {
  orderShot: number;
  hasMilk?: boolean;
  hasSalt?: boolean;
};

interface CoffeeMaker {
  makeCoffee(shots: number): CoffeeCup;
}

// CoffeeMaker ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” CoffeMachine ํด๋ž˜์Šค์ด๋‹ค.
class CoffeMachine implements CoffeeMaker {
  protected static ONE_SHOT_CAPSULE: number = 3;
  protected static ONE_CUP_WATER: number = 10;

  static makeMachine(beans: number, water: number): CoffeMachine {
    return new CoffeMachine(beans, water);
  }

  public constructor(
    protected capsule: number = 3,
    protected water: number = 10
  ) {}

  makeCoffee(orderShot: number): CoffeeCup {
    this.checkMaterials(orderShot);
    console.log("์บก์А์“ฐ๊ธฐ ์ „ " + this.capsule);
    this.useCapsule(orderShot);
    console.log("๋ฌผ์“ฐ๊ธฐ ์ „ " + this.water);
    this.useWater();
    this.heatWater();
    return this.extract(orderShot);
  }

  protected checkMaterials(orderShot: number) {
    if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
      throw new Error(`์ปคํ”ผ์บก์А ๋ถ€์กฑ!!! ํ˜„์žฌ ๋ณด์œ  ์บก์А : ${this.capsule}`);
    }
    if (this.water < CoffeMachine.ONE_CUP_WATER) {
      throw new Error(`๋ฌผ ๋ถ€์กฑ!!! ๋‚จ์€ ๋ฌผ ${this.water}`);
    }
  }
  clean(): void {
    console.log("์ปคํ”ผ๋จธ์‹  ํ–‰๊ตฌ๋Š” ์ค‘!");
  }

  private extract(shots: number): CoffeeCup {
    return {
      orderShot: shots,
      hasMilk: false,
    };
  }
  private heatWater() {
    console.log("๋ฌผ ๋“์ด๋Š” ์ค‘...");
  }

  private useCapsule(shot: number) {
    console.log("์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
    console.log("์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„" + this.capsule);
  }

  protected useWater() {
    console.log("๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.water -= CoffeMachine.ONE_CUP_WATER;
    console.log("๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ " + this.water);
  }

  addCapsule(capsule: number) {
    this.capsule += capsule;
  }

  fulfillWater(water: number) {
    this.water += water;
  }

  get Water(): number {
    return this.water;
  }

  get Capsule(): number {
    return this.capsule;
  }
}

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.

class CafeLatteMachine extends CoffeMachine {
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜

    //๋ถ€๋ชจ์—์„œ ๋ฐ›์•„์˜จ ์ปคํ”ผ ์™„์„ฑํ’ˆ์— ์šฐ์œ ๋งŒ ๋ถ€์–ด์ฃผ์ž!!!
    this.steamMilk();
    this.pourMilk();

    return {
      ...coffee,
      hasMilk: true,
    };
  }

  private steamMilk(): void {
    console.log("์šฐ์œ  ๋ฐ์šฐ๋Š” ์ค‘...");
  }

  private pourMilk() {
    console.log("์šฐ์œ  ๋ถ“๋Š” ์ค‘...");
  }
}

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ saltCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.
class saltCoffeeMachine extends CoffeMachine {
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);

    //์†Œ๊ธˆ์„ ๋ฟŒ๋ฆฐ๋‹ค.
    this.addSalt();
    return {
      ...coffee,
      hasSalt: true,
    };
  }

  addSalt() {
    console.log("์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘");
  }
}

const machines: CoffeeMaker[] = [
  new CoffeMachine(25, 25),
  new CafeLatteMachine(15, 25),
  new saltCoffeeMachine(5, 10),
];

machines.forEach((machine) => {
  console.log("------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------");
  console.log(machine.makeCoffee(1));
});

<์ฝ”๋“œ ์ƒˆ์š”์†Œ ์ถ”๊ฐ€์ „ ์ถœ๋ ฅ ๊ฒฐ๊ณผ>

------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------
์บก์А์“ฐ๊ธฐ ์ „ 25
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„22
๋ฌผ์“ฐ๊ธฐ ์ „ 25
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 15
๋ฌผ ๋“์ด๋Š” ์ค‘...
{ orderShot: 1, hasMilk: false }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------
์บก์А์“ฐ๊ธฐ ์ „ 15
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„12
๋ฌผ์“ฐ๊ธฐ ์ „ 25
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 15
๋ฌผ ๋“์ด๋Š” ์ค‘...
์šฐ์œ  ๋ฐ์šฐ๋Š” ์ค‘...
์šฐ์œ  ๋ถ“๋Š” ์ค‘...
{ orderShot: 1, hasMilk: true }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------
์บก์А์“ฐ๊ธฐ ์ „ 5
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„2
๋ฌผ์“ฐ๊ธฐ ์ „ 10
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 0
๋ฌผ ๋“์ด๋Š” ์ค‘...
์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘
{ orderShot: 1, hasMilk: false, hasSalt: true }

์ƒ์†๋งŒ์„ ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๋ฌด์–ธ๊ฐ€ ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ ์—์„œ ์šฐ์œ ๊ฐ€์ ธ์˜ค๊ณ ~ ์†Œ๊ธˆ์ปคํ”ผ๋จธ์‹ ์—์„œ ์†Œ๊ธˆ๊ฐ€์ ธ์˜ค๊ณ ~ ํ•ด์•ผ๊ฒ ์ง€๋งŒ

์ฐจ๋ผ๋ฆฌ ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค์™€ ์†Œ๊ธˆํ†ต ํด๋ž˜์Šค๊ฐ€ ๋”ฐ๋กœ์žˆ์–ด์„œ ํ•„์š”ํ•  ๋•Œ ๋งˆ๋‹ค ๊ฐ€์ ธ๋‹ค ๋ถ™์ด๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ผ ๊ฒƒ์ด๊ณ 

์ปดํฌ์ง€์…˜์€ ๊ทธ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ค€๋‹ค!

 

 

 

์šฐ์„  ๋‹ค์Œ๊ณผ ๊ฐ™์ด

ํ‰๋ฒ”ํ•œ ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค์™€ ์†Œ๊ธˆ๋ฏน์„œ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด์ค€๋‹ค.

์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค ์ž์ฒด์ ์œผ๋กœ ์šฐ์œ ๊ฑฐํ’ˆ์„ ๋งŒ๋“ค๊ณ , ์™ธ๋ถ€์—์„œ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์˜ฌ ๊ฒฝ์šฐ ๋‚ด๋ถ€์—์„œ ๋งŒ๋“  ์šฐ์œ ๊ฑฐํ’ˆ์„ ์˜ฌ๋ฆฐ ์ปคํ”ผ์ปต์„ ๋ฐ˜ํ™˜ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

์†Œ๊ธˆ ๋ฏน์„œ ํด๋ž˜์Šค๋Š” ๋‚ด๋ถ€์—์„œ ์†Œ๊ธˆ์„ ์ง‘์–ด์˜ฌ๋ฆฌ๊ณ , ์™ธ๋ถ€์—์„œ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์˜ฌ ๊ฒฝ์šฐ ๋‚ด๋ถ€์—์„œ ์ง‘์–ด๋“  ์†Œ๊ธˆ์„ ๋ฟŒ๋ ค ๊ทธ ์ปคํ”ผ์ปต์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋„๋ก ๋งŒ๋“ค์–ด๋ณธ๋‹ค. 

//   //์ปคํ”ผ๋จธ์‹  ๋งŒ๋“ค๊ธฐ
type CoffeeCup = {
  orderShot: number;
  hasMilk?: boolean;
  hasSalt?: boolean;
};

interface CoffeeMaker {
  makeCoffee(shots: number): CoffeeCup;
}

//์ผ๋ฐ˜ ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ//////////////////////////////////////////////////////////////////////
class CheapMilkSteamer {
  //(1)์šฐ์œ  ๊ฑฐํ’ˆ์„ ๋งŒ๋“œ๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜
  private steamMilk(): void {
    console.log("๋ชฝ๊ธ€๋ชฝ๊ธ€ ํฌ์‚ญํฌ์‚ญํ•œ ์šฐ์œ ํผ");
  }
  //(2)๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์„œ, ๋งŒ๋“ค์–ด์ง„ ์šฐ์œ ๊ฑฐํ’ˆ(1)์„ ๋ถ€์–ด์„œ ์ด ์ปคํ”ผ์ปต์„ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜
  addMilkform(cup: CoffeeCup): CoffeeCup {
    this.steamMilk();
    return {
      ...cup,
      hasMilk: true,
    };
  }
}

//์†Œ๊ธˆ๋ฏน์„œ///////////////////////////////////////////////////////////////////////////////
class SaltMixer {
  //(1)์†Œ๊ธˆ์„ ์ง‘๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜
  private getSalt() {
    console.log("์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘ ์ง‘์—ˆ๋‹ค");
    return true;
  }
  //(2)๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์„œ, ์ง‘์€ ์†Œ๊ธˆ(1)์„ ๋ฟŒ๋ ค์„œ ์ด ์ปคํ”ผ์ปต์„ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜
  addSalt(cup: CoffeeCup): CoffeeCup {
    const salt = this.getSalt();
    return {
      ...cup,
      hasSalt: salt,
    };
  }
}
// CoffeeMaker ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” CoffeMachine ํด๋ž˜์Šค์ด๋‹ค.
class CoffeMachine implements CoffeeMaker {
  protected static ONE_SHOT_CAPSULE: number = 3;
  protected static ONE_CUP_WATER: number = 10;

  static makeMachine(beans: number, water: number): CoffeMachine {
    return new CoffeMachine(beans, water);
  }

  public constructor(
    protected capsule: number = 3,
    protected water: number = 10
  ) {}

  makeCoffee(orderShot: number): CoffeeCup {
    this.checkMaterials(orderShot);
    console.log("์บก์А์“ฐ๊ธฐ ์ „ " + this.capsule);
    this.useCapsule(orderShot);
    console.log("๋ฌผ์“ฐ๊ธฐ ์ „ " + this.water);
    this.useWater();
    this.heatWater();
    return this.extract(orderShot);
  }

  protected checkMaterials(orderShot: number) {
    if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
      throw new Error(`์ปคํ”ผ์บก์А ๋ถ€์กฑ!!! ํ˜„์žฌ ๋ณด์œ  ์บก์А : ${this.capsule}`);
    }
    if (this.water < CoffeMachine.ONE_CUP_WATER) {
      throw new Error(`๋ฌผ ๋ถ€์กฑ!!! ๋‚จ์€ ๋ฌผ ${this.water}`);
    }
  }
  clean(): void {
    console.log("์ปคํ”ผ๋จธ์‹  ํ–‰๊ตฌ๋Š” ์ค‘!");
  }

  private extract(shots: number): CoffeeCup {
    return {
      orderShot: shots,
      hasMilk: false,
    };
  }
  private heatWater() {
    console.log("๋ฌผ ๋“์ด๋Š” ์ค‘...");
  }

  private useCapsule(shot: number) {
    console.log("์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
    console.log("์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„" + this.capsule);
  }

  protected useWater() {
    console.log("๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.water -= CoffeMachine.ONE_CUP_WATER;
    console.log("๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ " + this.water);
  }

  addCapsule(capsule: number) {
    this.capsule += capsule;
  }

  fulfillWater(water: number) {
    this.water += water;
  }

  get Water(): number {
    return this.water;
  }

  get Capsule(): number {
    return this.capsule;
  }
}

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.

class CafeLatteMachine extends CoffeMachine {
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜

    //๋ถ€๋ชจ์—์„œ ๋ฐ›์•„์˜จ ์ปคํ”ผ ์™„์„ฑํ’ˆ์— ์šฐ์œ ๋งŒ ๋ถ€์–ด์ฃผ์ž!!!//////////////////////////////////////////////
    this.steamMilk();
    this.pourMilk();

    return {
      ...coffee,
      hasMilk: true,
    };
  }

  private steamMilk(): void {
    console.log("์šฐ์œ  ๋ฐ์šฐ๋Š” ์ค‘...");
  }

  private pourMilk() {
    console.log("์šฐ์œ  ๋ถ“๋Š” ์ค‘...");
  }
}

// CoffeMachine ํด๋ž˜์Šค ๋ฅผ ์ƒ์†๋ฐ›์€ saltCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.
class saltCoffeeMachine extends CoffeMachine {
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);

    //์†Œ๊ธˆ์„ ๋ฟŒ๋ฆฐ๋‹ค.//////////////////////////////////////////////////////////////////////
    this.addSalt();
    return {
      ...coffee,
      hasSalt: true,
    };
  }

  private addSalt() {
    console.log("์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘");
  }
}

const machines: CoffeeMaker[] = [
  new CoffeMachine(25, 25),
  new CafeLatteMachine(15, 25),
  new saltCoffeeMachine(5, 10),
];

machines.forEach((machine) => {
  console.log("------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------");
  console.log(machine.makeCoffee(1));
});

 

์—ฌ๊ธฐ๊นŒ์ง€ ๋งŒ๋“ค์—ˆ์œผ๋ฉด ์นดํŽ˜๋ผ๋–ผ๋จธ์‹  ๋‚ด๋ถ€์—์„œ ๊ตณ์ด ์šฐ์œ ๋ฅผ ๋งŒ๋“ค๊ณ  ๋ถ€์–ด์ฃผ๋Š” ๋‚ด๋ถ€ ํ™œ๋™์ด ํ•„์š”ํ•œ์ง€,

์†Œ๊ธˆ์ปคํ”ผ๋จธ์‹  ๋‚ด๋ถ€์—์„œ ๊ตณ์ด ์†Œ๊ธˆ์„ ์ง‘์–ด์„œ ๋ฟŒ๋ ค์ฃผ๋Š” ๋‚ด๋ถ€ ํ™œ๋™์ด ํ•„์š”ํ•œ์ง€์— ๋Œ€ํ•œ ์˜์‹ฌ์ด ํ•„์š”ํ•œ๋‹ค.

 

๋งŒ๋“ค์–ด ๋‘” ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค์™€ ์†Œ๊ธˆ๋ฏน์„œ ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์„ค๊ณ„์ƒ ๋” ๋‚˜์„ ๋“ฏํ•˜๋‹ค. 

 

 

์นดํŽ˜๋ผ๋–ผ ๋จธ์‹ ๋ถ€ํ„ฐ ๊ณ ์ณ๋ณธ๋‹ค.

 

1. ์นดํŽ˜๋ผ๋–ผ๋จธ์‹  ๋‚ด๋ถ€์—์„œ ์šฐ์œ  ๊ด€๋ จ ๋กœ์ง์„ ๊ฑท์–ด๋‚ธ๋‹ค.

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.

class CafeLatteMachine extends CoffeMachine {
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜

    return {
      ...coffee,
      hasMilk: true,
    };
  }
}

2. ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค์—์„œ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์„ ๋ฐ›์•„์˜ค์ž

์ด๊ฒƒ์€ dependency injection(https://ko.wikipedia.org/wiki/%EC%9D%98%EC%A1%B4%EC%84%B1_%EC%A3%BC%EC%9E%85)

์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\\

class CafeLatteMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }

  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜

    return {
      ...coffee,
      hasMilk: true,
    };
  }
}

3. ์ด์ œ ์ง์ ‘์ ์œผ๋กœ hasMilk ํ”„๋กœํผํ‹ฐ๋ฅผ true๋กœ ๋ณ€๊ฒฝํ•ด์„œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋˜ ๋กœ์ง๋„ ๊ฑท์–ด๋‚ด๊ณ 

milkFrother์— milk๋ฅผ ๋ฐ”๋กœ ์ „๋‹ฌํ•ด์ฃผ์ž.

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\\

class CafeLatteMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }

  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜
    return this.milkFrother.addMilkform(coffee);
  }
}

์†Œ๊ธˆ์ปคํ”ผ ๋จธ์‹ ๋„ ์œ„์™€ ๋น„์Šทํ•˜๊ฒŒ ๊ณ ์ณ๋ณธ๋‹ค.

1. ์†Œ๊ธˆ์ปคํ”ผ๋จธ์‹  ๋‚ด๋ถ€์—์„œ ์†Œ๊ธˆ ๊ด€๋ จ ๋กœ์ง์„ ๊ฑท์–ด๋‚ธ๋‹ค.

class saltCoffeeMachine extends CoffeMachine {
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);
    return {
      ...coffee,
      hasSalt: true,
    };
  }
}

 

2. ์†Œ๊ธˆ๋ฏน์„œ ํด๋ž˜์Šค์—์„œ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์„ ๋ฐ›์•„์˜ค์ž

์ด๊ฒƒ์€ dependency injection(https://ko.wikipedia.org/wiki/%EC%9D%98%EC%A1%B4%EC%84%B1_%EC%A3%BC%EC%9E%85)

์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.

 

class saltCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);

    return {
      ...coffee,
      hasSalt: true,
    };
  }
}

 

 

3. ์ด์ œ ์ง์ ‘์ ์œผ๋กœ hasMilk ํ”„๋กœํผํ‹ฐ๋ฅผ true๋กœ ๋ณ€๊ฒฝํ•ด์„œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋˜ ๋กœ์ง๋„ ๊ฑท์–ด๋‚ด๊ณ 

์†Œ๊ธˆํ† ํ•‘์— ์†”ํŠธ๋ฏน์„œ๋ฅผ ๋ฐ”๋กœ ์ „๋‹ฌํ•ด์ฃผ์ž.

class saltCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);
    return this.saltTopping.addSalt(coffee);
  }
}

 

 

<ํ˜„์žฌ๊นŒ์ง€ ์†Œ์Šค์ฝ”๋“œ>

//   //์ปคํ”ผ๋จธ์‹  ๋งŒ๋“ค๊ธฐ
type CoffeeCup = {
  orderShot: number;
  hasMilk?: boolean;
  hasSalt?: boolean;
};

interface CoffeeMaker {
  makeCoffee(shots: number): CoffeeCup;
}

//์ผ๋ฐ˜ ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ//////////////////////////////////////////////////////////////////////
class CheapMilkSteamer {
  //(1)์šฐ์œ  ๊ฑฐํ’ˆ์„ ๋งŒ๋“œ๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜
  private steamMilk(): void {
    console.log("๋ชฝ๊ธ€๋ชฝ๊ธ€ ํฌ์‚ญํฌ์‚ญํ•œ ์šฐ์œ ํผ");
  }
  //(2)๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์„œ, ๋งŒ๋“ค์–ด์ง„ ์šฐ์œ ๊ฑฐํ’ˆ(1)์„ ๋ถ€์–ด์„œ ์ด ์ปคํ”ผ์ปต์„ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜
  addMilkform(cup: CoffeeCup): CoffeeCup {
    this.steamMilk();
    return {
      ...cup,
      hasMilk: true,
    };
  }
}

//์†Œ๊ธˆ๋ฏน์„œ///////////////////////////////////////////////////////////////////////////////
class SaltMixer {
  //(1)์†Œ๊ธˆ์„ ์ง‘๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜
  private getSalt() {
    console.log("์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘ ์ง‘์—ˆ๋‹ค");
    return true;
  }
  //(2)๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์„œ, ์ง‘์€ ์†Œ๊ธˆ(1)์„ ๋ฟŒ๋ ค์„œ ์ด ์ปคํ”ผ์ปต์„ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜
  addSalt(cup: CoffeeCup): CoffeeCup {
    const salt = this.getSalt();
    return {
      ...cup,
      hasSalt: salt,
    };
  }
}
// CoffeeMaker ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” CoffeMachine ํด๋ž˜์Šค์ด๋‹ค.////////////////////////////
class CoffeMachine implements CoffeeMaker {
  protected static ONE_SHOT_CAPSULE: number = 3;
  protected static ONE_CUP_WATER: number = 10;

  static makeMachine(beans: number, water: number): CoffeMachine {
    return new CoffeMachine(beans, water);
  }

  public constructor(
    protected capsule: number = 3,
    protected water: number = 10
  ) {}

  makeCoffee(orderShot: number): CoffeeCup {
    this.checkMaterials(orderShot);
    console.log("์บก์А์“ฐ๊ธฐ ์ „ " + this.capsule);
    this.useCapsule(orderShot);
    console.log("๋ฌผ์“ฐ๊ธฐ ์ „ " + this.water);
    this.useWater();
    this.heatWater();
    return this.extract(orderShot);
  }

  protected checkMaterials(orderShot: number) {
    if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
      throw new Error(`์ปคํ”ผ์บก์А ๋ถ€์กฑ!!! ํ˜„์žฌ ๋ณด์œ  ์บก์А : ${this.capsule}`);
    }
    if (this.water < CoffeMachine.ONE_CUP_WATER) {
      throw new Error(`๋ฌผ ๋ถ€์กฑ!!! ๋‚จ์€ ๋ฌผ ${this.water}`);
    }
  }
  clean(): void {
    console.log("์ปคํ”ผ๋จธ์‹  ํ–‰๊ตฌ๋Š” ์ค‘!");
  }

  private extract(shots: number): CoffeeCup {
    return {
      orderShot: shots,
      hasMilk: false,
    };
  }
  private heatWater() {
    console.log("๋ฌผ ๋“์ด๋Š” ์ค‘...");
  }

  private useCapsule(shot: number) {
    console.log("์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
    console.log("์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„" + this.capsule);
  }

  protected useWater() {
    console.log("๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.water -= CoffeMachine.ONE_CUP_WATER;
    console.log("๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ " + this.water);
  }

  addCapsule(capsule: number) {
    this.capsule += capsule;
  }

  fulfillWater(water: number) {
    this.water += water;
  }

  get Water(): number {
    return this.water;
  }

  get Capsule(): number {
    return this.capsule;
  }
}

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\\

class CafeLatteMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }

  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜
    return this.milkFrother.addMilkform(coffee);
  }
}

// CoffeMachine ํด๋ž˜์Šค ๋ฅผ ์ƒ์†๋ฐ›์€ saltCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\
class saltCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);
    return this.saltTopping.addSalt(coffee);
  }
}

const machines: CoffeeMaker[] = [
  new CoffeMachine(25, 25),
  new CafeLatteMachine(15, 25, new CheapMilkSteamer()),
  new saltCoffeeMachine(5, 10, new SaltMixer()),
];

machines.forEach((machine) => {
  console.log("------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!-- ----------");
  console.log(machine.makeCoffee(1));
});

 

<์ถœ๋ ฅ ๊ฒฐ๊ณผ> awesome!! ! ์•„์ฃผ ์ž˜ ์ž‘๋™ํ•œ๋‹ค.

 


------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------
์บก์А์“ฐ๊ธฐ ์ „ 25
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„22
๋ฌผ์“ฐ๊ธฐ ์ „ 25
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 15
๋ฌผ ๋“์ด๋Š” ์ค‘...
{ orderShot: 1, hasMilk: false }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------
์บก์А์“ฐ๊ธฐ ์ „ 15
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„12
๋ฌผ์“ฐ๊ธฐ ์ „ 25
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 15
๋ฌผ ๋“์ด๋Š” ์ค‘...
๋ชฝ๊ธ€๋ชฝ๊ธ€ ํฌ์‚ญํฌ์‚ญํ•œ ์šฐ์œ ํผ
{ orderShot: 1, hasMilk: true }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!------------
์บก์А์“ฐ๊ธฐ ์ „ 5
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„2
๋ฌผ์“ฐ๊ธฐ ์ „ 10
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 0
๋ฌผ ๋“์ด๋Š” ์ค‘...
์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘ ์ง‘์—ˆ๋‹ค
{ orderShot: 1, hasMilk: false, hasSalt: true }

 

์ด๋ ‡๊ฒŒ ๊ฐ๊ฐ์˜ ํด๋ž˜์Šค์—์„œ ํ•„์š”ํ•œ ๊ฒƒ์„ ๋งค๋ฒˆ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ๋งค๋ฒˆ ์ƒ์†์„ ํ•ด์„œ ์ƒˆ๋กœ์šด ์š”์†Œ๋“ค์„ ์ง‘์–ด๋„ฃ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ธฐ ๋ณด๋‹ค๋Š”

๊ฐ๊ฐ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค๋ฉด(์ด ์˜ˆ์ œ์—์„œ๋Š” ์šฐ์œ ๊ฑฐํ’ˆ๊ธฐํด๋ž˜์Šค์™€ ์†Œ๊ธˆ๋ฏน์„œ ํด๋ž˜์Šค)

์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค๋กœ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด๋‘ ์œผ๋กœ์จ ํ•„์š”ํ•œ ๊ณณ์— ๊ฐ€์ ธ๋‹ค๊ฐ€ ๋ถ™์—ฌ์“ฐ๋Š”!

์ปดํฌ์ง€์…˜์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์„ค๊ณ„์ƒ ๋” ์ด๋กœ์šด ์ ์ด ์žˆ๋‹ค.(์ƒ์†์˜ ๋‚จ๋ฐœ๋ณด๋‹ค๋Š”)

 

์ด๊ฑธ๋กœ ์ œ์ผ ์ฒ˜์Œ์— ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋˜

 

์†Œ๊ธˆ์นดํŽ˜๋ผํ…Œ์ปคํ”ผ๋จธ์‹  ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊นŒ?

 

// ์ฒ˜์Œ๋ถ€ํ„ฐ ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋˜ saltCafeLatteCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\
class saltCafeLatteCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    let coffee = super.makeCoffee(orderShot);
    coffee = this.saltTopping.addSalt(coffee);
    return this.milkFrother.addMilkform(coffee);
  }

์ด์  ! ๋ถ€ํ’ˆ ๋ถ™์ด๋“ฏ์ด ํด๋ž˜์Šค๋ฅผ ๋”์šฑ ์‰ฝ๊ฒŒ์ฐ์–ด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค~!!!

์œ„ ํด๋ž˜์Šค๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์“ฐ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

// ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋˜ saltCafeLatteCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\
class saltCafeLatteCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    let coffee = super.makeCoffee(orderShot);
    return this.milkFrother.addMilkform(this.saltTopping.addSalt(coffee));
  }
}

 

์ด๊ฑธ ๋” ์„ธ๋ จ๋˜๊ฒŒ ์ž‘์„ฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ •๋ฆฌํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\\

class CafeLatteMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }

  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜
    const saltAdded = this.milkFrother.addMilkform(coffee);
    return this.milkFrother.addMilkform(saltAdded);
  }
}

 

<์ตœ์ข… ์ „์ฒด ์ฝ”๋“œ>

//   //์ปคํ”ผ๋จธ์‹  ๋งŒ๋“ค๊ธฐ
type CoffeeCup = {
  orderShot: number;
  hasMilk?: boolean;
  hasSalt?: boolean;
};

interface CoffeeMaker {
  makeCoffee(shots: number): CoffeeCup;
}

//์ผ๋ฐ˜ ์šฐ์œ  ๊ฑฐํ’ˆ๊ธฐ//////////////////////////////////////////////////////////////////////
class CheapMilkSteamer {
  //(1)์šฐ์œ  ๊ฑฐํ’ˆ์„ ๋งŒ๋“œ๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜
  private steamMilk(): void {
    console.log("๋ชฝ๊ธ€๋ชฝ๊ธ€ ํฌ์‚ญํฌ์‚ญํ•œ ์šฐ์œ ํผ");
  }
  //(2)๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์„œ, ๋งŒ๋“ค์–ด์ง„ ์šฐ์œ ๊ฑฐํ’ˆ(1)์„ ๋ถ€์–ด์„œ ์ด ์ปคํ”ผ์ปต์„ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜
  addMilkform(cup: CoffeeCup): CoffeeCup {
    this.steamMilk();
    return {
      ...cup,
      hasMilk: true,
    };
  }
}

//์†Œ๊ธˆ๋ฏน์„œ///////////////////////////////////////////////////////////////////////////////
class SaltMixer {
  //(1)์†Œ๊ธˆ์„ ์ง‘๋Š” ๋‚ด๋ถ€ ํ•จ์ˆ˜
  private getSalt() {
    console.log("์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘ ์ง‘์—ˆ๋‹ค");
    return true;
  }
  //(2)๋งŒ๋“ค์–ด์ง„ ์ปคํ”ผ์ปต์„ ๋ฐ›์•„์„œ, ์ง‘์€ ์†Œ๊ธˆ(1)์„ ๋ฟŒ๋ ค์„œ ์ด ์ปคํ”ผ์ปต์„ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜
  addSalt(cup: CoffeeCup): CoffeeCup {
    const salt = this.getSalt();
    return {
      ...cup,
      hasSalt: salt,
    };
  }
}
// CoffeeMaker ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” CoffeMachine ํด๋ž˜์Šค์ด๋‹ค.////////////////////////////
class CoffeMachine implements CoffeeMaker {
  protected static ONE_SHOT_CAPSULE: number = 3;
  protected static ONE_CUP_WATER: number = 10;

  static makeMachine(beans: number, water: number): CoffeMachine {
    return new CoffeMachine(beans, water);
  }

  public constructor(
    protected capsule: number = 3,
    protected water: number = 10
  ) {}

  makeCoffee(orderShot: number): CoffeeCup {
    this.checkMaterials(orderShot);
    console.log("์บก์А์“ฐ๊ธฐ ์ „ " + this.capsule);
    this.useCapsule(orderShot);
    console.log("๋ฌผ์“ฐ๊ธฐ ์ „ " + this.water);
    this.useWater();
    this.heatWater();
    return this.extract(orderShot);
  }

  protected checkMaterials(orderShot: number) {
    if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
      throw new Error(`์ปคํ”ผ์บก์А ๋ถ€์กฑ!!! ํ˜„์žฌ ๋ณด์œ  ์บก์А : ${this.capsule}`);
    }
    if (this.water < CoffeMachine.ONE_CUP_WATER) {
      throw new Error(`๋ฌผ ๋ถ€์กฑ!!! ๋‚จ์€ ๋ฌผ ${this.water}`);
    }
  }
  clean(): void {
    console.log("์ปคํ”ผ๋จธ์‹  ํ–‰๊ตฌ๋Š” ์ค‘!");
  }

  private extract(shots: number): CoffeeCup {
    return {
      orderShot: shots,
      hasMilk: false,
    };
  }
  private heatWater() {
    console.log("๋ฌผ ๋“์ด๋Š” ์ค‘...");
  }

  private useCapsule(shot: number) {
    console.log("์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
    console.log("์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„" + this.capsule);
  }

  protected useWater() {
    console.log("๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.");
    this.water -= CoffeMachine.ONE_CUP_WATER;
    console.log("๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ " + this.water);
  }

  addCapsule(capsule: number) {
    this.capsule += capsule;
  }

  fulfillWater(water: number) {
    this.water += water;
  }

  get Water(): number {
    return this.water;
  }

  get Capsule(): number {
    return this.capsule;
  }
}

// CoffeMachine ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ CafeLatteMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\\

class CafeLatteMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }

  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์А ์†Œ๋น„, ๋ฌผ ์†Œ๋น„, ๋ฌผ ๊ฐ€์—ด ๋‹ค ๋๋‚˜๊ณ  ์™„์„ฑ๋œ ์ปคํ”ผ๊ฐ€ ๋ฐ˜ํ™˜
    return this.milkFrother.addMilkform(coffee);
  }
}

// CoffeMachine ํด๋ž˜์Šค ๋ฅผ ์ƒ์†๋ฐ›์€ saltCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\
class saltCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);
    return this.saltTopping.addSalt(coffee);
  }
}

// ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋˜ saltCafeLatteCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\
class saltCafeLatteCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);
    const saltAdded = this.saltTopping.addSalt(coffee);
    return this.milkFrother.addMilkform(saltAdded);
  }
}

const machines: CoffeeMaker[] = [
  new CoffeMachine(25, 25),
  new CafeLatteMachine(15, 25, new CheapMilkSteamer()),
  new saltCoffeeMachine(5, 10, new SaltMixer()),
  new saltCafeLatteCoffeeMachine(
    5,
    10,
    new SaltMixer(),
    new CheapMilkSteamer()
  ),
];

machines.forEach((machine) => {
  console.log("------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!-- ----------");
  console.log(machine.makeCoffee(1));
});

<์ถœ๋ ฅ ๊ฒฐ๊ณผ>


------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!-- ----------
์บก์А์“ฐ๊ธฐ ์ „ 25
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„22
๋ฌผ์“ฐ๊ธฐ ์ „ 25
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 15
๋ฌผ ๋“์ด๋Š” ์ค‘...
{ orderShot: 1, hasMilk: false }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!-- ----------
์บก์А์“ฐ๊ธฐ ์ „ 15
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„12
๋ฌผ์“ฐ๊ธฐ ์ „ 25
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 15
๋ฌผ ๋“์ด๋Š” ์ค‘...
๋ชฝ๊ธ€๋ชฝ๊ธ€ ํฌ์‚ญํฌ์‚ญํ•œ ์šฐ์œ ํผ
{ orderShot: 1, hasMilk: true }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!-- ----------
์บก์А์“ฐ๊ธฐ ์ „ 5
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„2
๋ฌผ์“ฐ๊ธฐ ์ „ 10
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 0
๋ฌผ ๋“์ด๋Š” ์ค‘...
์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘ ์ง‘์—ˆ๋‹ค
{ orderShot: 1, hasMilk: false, hasSalt: true }
------------์ปคํ”ผ๋จธ์‹  ๊ฐ€๋™~!-- ----------
์บก์А์“ฐ๊ธฐ ์ „ 5
์บก์А์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
์บก์А ์“ฐ๊ณ  ๋‚œ ํ›„2
๋ฌผ์“ฐ๊ธฐ ์ „ 10
๋ฌผ์“ฐ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค.
๋ฌผ์“ฐ๊ณ  ๋‚œ ํ›„ 0
๋ฌผ ๋“์ด๋Š” ์ค‘...
์†Œ๊ธˆ์„ ํ•œ๊ผฌ์ง‘ ์ง‘์—ˆ๋‹ค
๋ชฝ๊ธ€๋ชฝ๊ธ€ ํฌ์‚ญํฌ์‚ญํ•œ ์šฐ์œ ํผ
{ orderShot: 1, hasMilk: true, hasSalt: true }

 

 

<์ตœ์ข… ์š”์•ฝ>

 

// ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋˜ saltCafeLatteCoffeeMachine ํด๋ž˜์Šค์ด๋‹ค.\\\\\\\\\\\\\\\\\\\\\\\\\\\
class saltCafeLatteCoffeeMachine extends CoffeMachine {
  public constructor(
    protected capsule: number = 3,
    protected water: number = 10,
    private saltTopping: SaltMixer,
    private milkFrother: CheapMilkSteamer
  ) {
    super(capsule, water);
  }
  makeCoffee(orderShot: number): CoffeeCup {
    const coffee = super.makeCoffee(orderShot);
    const saltAdded = this.saltTopping.addSalt(coffee);
    return this.milkFrother.addMilkform(saltAdded);
  }
}

์ด ํด๋ž˜์Šค๋Š” ์šฐ์œ ๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“œ๋Š”์ง€ ์†Œ๊ธˆ์€ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๋˜๋Š”๊ฑด์ง€ ์ „ํ˜€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๋Š”๋‹ค.

๋‹ค๋งŒ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ ธ์™€์„œ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›์Œ์œผ๋กœ์จ

์ปดํฌ์ง€์…˜์„ ์ด์šฉํ•ด์„œ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ๊ณ„์† ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ปดํฌ์ง€์…˜์€ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๊ต‰์žฅํžˆ ๋†’์—ฌ์ฃผ๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ๋‹ค.

๋‹ค๋งŒ, ์น˜๋ช…์ ์ธ ๋‹จ์ ์ด ์žˆ๋Š”๋ฐ ์šฐ์œ ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค, ์†Œ๊ธˆ๋ฏน์„œํด๋ž˜์Šค, ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ , ์†Œ๊ธˆ์ปคํ”ผ๋จธ์‹ , ์†Œ๊ธˆ์นดํŽ˜๋ผ๋–ผ๋จธ์‹  ์ด๋ ‡๊ฒŒ ์—ฐ๊ฒฐ๋œ ํด๋ž˜์Šค๋“ค ๊ฐ„์˜ ์ปคํ”Œ๋ง์ด ๋„ˆ๋ฌด ์‹ฌํ•˜๊ณ  ๊ฐ•๋ ฅํ•œ ์ ์ด ๋ฐ”๋กœ ๊ทธ๊ฒƒ์ด๋‹ค.

๋ฐ”๋กœ ๊ทธ ์šฐ์œ ๊ฑฐํ’ˆ๊ธฐ ํด๋ž˜์Šค์™€ ๋ฐ”๋กœ ๊ทธ ์†Œ๊ธˆ๋ฏน์„œ ํด๋ž˜์Šค๋งŒ์„ ์‚ฌ์šฉํ•ด์•ผํ•˜๋ฉฐ(ํ•ญ์ƒ ์Šค์Šค๋กœ๋ฅผ ์ œ์•ฝ),

๋‹ค๋ฅธ ๊ณ ๊ธ‰์šฐ์œ ๊ฑฐํ’ˆ๊ธฐํด๋ž˜์Šค ์„คํƒ•๋ฏน์„œ ํด๋ž˜์Šค ๋“ฑ์œผ๋กœ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํด๋ž˜์Šค ๋‚ด์šฉ์„ ๋‹ค์‹œ ๊ณ ์ณ์•ผํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํด๋ž˜์Šค ๊ฐ„ ์„œ๋กœ ๋„ˆ๋ฌด ์ž˜์•Œ๊ณ  ์žˆ๋Š” ๊ด€๊ณ„ํ˜•์„ฑ์€ ๊ฑด๊ฐ•ํ•˜์ง€ ๋ชปํ•˜๋‹ค.

ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋ฐ”๊พธ๋ฉด ๊ทธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ปคํ”Œ๋ง์ด ๊ฐ•ํ•œ ๋ชจ๋“  ํด๋ž˜์Šค๋“ค์„ ์—…๋ฐ์ดํŠธํ•ด์•ผํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ํด๋ž˜์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์€ ๋ฌธ์ œ ์ƒํ™ฉ๋“ค(์ปคํ”Œ๋ง)์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€?

๋”์šฑ ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์œ ์—ฐ์„ฑ ๋†’์€ ํ…Œํฌ๋‹‰์€ interface(๋ฐ”๋กœ ๋‹ค์Œ ํฌ์ŠคํŒ…, ์ด์™€ ๊ด€๋ จํ•œ ์ „๋žตํŒจํ„ด [ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] composition ์žฅ์ ์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ interface — My dev Note๐Ÿ“’ (tistory.com))๋กœ ๊ตฌ์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

728x90

'TypeScript > ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ TypeScript' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] Abstract ํด๋ž˜์Šค์™€ abstract method  (0) 2022.04.23
[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] composition ์žฅ์ ์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ interface  (0) 2022.04.23
[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] ๋‹คํ˜•์„ฑ(polymorphism)์ด ๋ญ๊ฐ€ ์ข‹์€ ๊ฒƒ์ผ๊นŒ?  (0) 2022.04.22
[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] ์ปคํ”ผ๋จธ์‹ ํด๋ž˜์Šค <-์ƒ์†- ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ ํด๋ž˜์Šค  (0) 2022.04.21
[ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] OOP ๋‹คํ˜•์„ฑ, ์ƒ์† ๊ฐœ๋… ํ™•์‹คํ•˜๊ฒŒ ์ •๋ฆฌ  (0) 2022.04.21
    'TypeScript/ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ TypeScript' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • [ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] Abstract ํด๋ž˜์Šค์™€ abstract method
    • [ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] composition ์žฅ์ ์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ interface
    • [ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] ๋‹คํ˜•์„ฑ(polymorphism)์ด ๋ญ๊ฐ€ ์ข‹์€ ๊ฒƒ์ผ๊นŒ?
    • [ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ] ์ปคํ”ผ๋จธ์‹ ํด๋ž˜์Šค <-์ƒ์†- ์นดํŽ˜๋ผ๋–ผ๋จธ์‹ ํด๋ž˜์Šค
    Rainbow๐ŸŒˆCoder
    Rainbow๐ŸŒˆCoder
    ๋ชฐ๋ผ๋„ ๊ฒฐ๊ตญ์€ ์•„๋Š” ๊ฐœ๋ฐœ์ž, ๊ทธ๋Ÿฐ ์‚ฌ๋žŒ์ด ๋˜๊ธฐ ์œ„ํ•œ ๋งค์ผ์˜ ํ•œ๊ฑธ์Œ

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”