A A
[Design Pattern] Template Method Pattern - ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด

Templete Method Pattern

ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด(Template Method Pattern)์€ ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ๊ธฐ๋ณธ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๊ณ , ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํŠน์ • ๋‹จ๊ณ„๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.
  • ์ด ํŒจํ„ด์„ ํ†ตํ•ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๊ตฌ์กฐ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํŠน์ • ๋‹จ๊ณ„๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • ํ…œํ”Œ๋ฆฟ์ด๋ž€, ์‚ฌ์ „์  ์˜๋ฏธ๋กœ๋Š” ํ˜•ํŒ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฌธ์ž, ๋„ํ˜•์œผ๋กœ ๊ตฌ๋ฉ์ด ๋šซ๋ ค ์žˆ๋Š” ์–‡์€ ํ”Œ๋ผ์Šคํ‹ฑ ํŒ์„ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‹ค์ œ๋กœ ์–ด๋–ค ๋„ํ˜•์ด ๊ทธ๋ ค์งˆ์ง€๋Š” ํ•„๊ธฐ๊ตฌ์— ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
  • ํŽœ์œผ๋กœ ๊ทธ๋ฆฌ๋ฉด ํŽœ์œผ๋กœ ๊ทธ๋ฆฐ ๋„ํ˜•์ด ๋˜๊ณ , ์—ฐํ•„๋กœ ๊ทธ๋ฆฌ๋ฉด ์—ฐํ•„๋กœ ๊ทธ๋ฆฐ ๋„ํ˜•์ด ๋ฉ๋‹ˆ๋‹ค.

์ถ”์ƒ Method๋กœ ๊ตฌํ˜„ํ•˜๋ฉด Templete Method๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

  • Template Method ํŒจํ„ด์€ ํ…œํ”Œ๋ฆฟ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.
  • ์ƒ์œ„ ํด๋ž˜์Šค ์ชฝ์— ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๊ณ , ๊ทธ ๋ฉ”์„œ๋“œ ์ •์˜ ์•ˆ์—๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ํ”„๋กœ๊ทธ๋žจ๋งŒ ๋ณด๋ฉด ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋“ค์„ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ํ•˜์œ„ ํด๋ž˜์Šค์ด๋ฉฐ, ํ•˜์œ„ ํด๋ž˜์Šค ์†์—์„œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
  • ์„œ๋กœ ๋‹ค๋ฅธ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ตฌํ˜„์„ ์‹คํ–‰ํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์ฒ˜๋ฆฌ๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜, ํ•˜์œ„ ํด๋ž˜์Šค๋“ค์—์„œ ์–ด๋–ค ๊ตฌํ˜„์„ ํ•˜๋”๋ผ๋„ ์ฒ˜๋ฆฌ์˜ ํฐ ํ๋ฆ„์€ ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ๊ฒฐ์ •ํ•œ ๋Œ€๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.
  • ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ๋ผˆ๋Œ€๋ฅผ ๊ฒฐ์ •ํ•˜๋ฉฐ, ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ๋Š” ๊ทธ ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ์„ ๊ฒฐ์ •ํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

Class์˜ Method๋“ค์ด Templete์œผ๋กœ ์ œ๊ณต๋˜๋Š” Pattern

 

 

  • Base class์—๋Š” Template method๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
  • Client๋Š” Template method๋งŒ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • Template method ๋‚ด๋ถ€์—์„œ ์—ฌ๋Ÿฌ step ํ•จ์ˆ˜ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • Step ํ•จ์ˆ˜๋“ค์€ Base class์—์„œ ์ œ๊ณต๋˜๋Š” abstract method์ž…๋‹ˆ๋‹ค.
  • Base class์—์„œ ์ƒ์†๋ฐ›์€ Child class๋Š” abstract method์ธ step ํ•จ์ˆ˜๋“ค์„ overrideํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์ƒ๊น๋‹ˆ๋‹ค.
Child class๋Š” step2()๋ฅผ override ํ–ˆ์œผ๋ฏ€๋กœ  Child object์˜ Template Method๋Š”?
Base class์˜ step1() -> Child class์˜ step2() -> Base class์˜ step3() ์ˆœ์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

Example - ๋ผ๋ฉด ๋“์ด๋Š” ๋ ˆ์‹œํ”ผ

  • BasicRecipe class๋Š” Template method๋กœ CookRamen์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • CookRamen์€ ๋‚ด๋ถ€์ ์œผ๋กœ boilWater, addRamen, wait ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋ผ๋ฉด ๋ ˆ์‹œํ”ผ๊ฐ€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • BasicRecipe๋ฅผ ์ƒ์†๋ฐ›์•„์„œ Recipe1, Recipe2๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • Recipe1์€ ๋ฌผ์„ ๋งŽ์ด ๋„ฃ๊ณ  ๋“์ด๋Š” ๋ ˆ์‹œํ”ผ
      • boilWater()๋ฅผ override
    • Recipe2๋Š” ๋ผ๋ฉด์„ ์˜ค๋ž˜ ๋“์ด๋Š” ๋ ˆ์‹œํ”ผ
      • wait()์„ override

๊ธฐ๋ณธ ํด๋ž˜์Šค ๊ตฌ์กฐ

class BasicRamenRecipe:
    def cookRamen(self):
        self.boilWater()
        self.addRamen()
        self.addons()
        self.wait()

    def boilWater(self):
        print("boil 550ml of water")

    def addRamen(self):
        print("add noodles, soup base, flakes")

    def addons(self):
        pass

    def wait(self):
        print("cook for 4min 30s")

 

 

 

  • BasicRamenRecipe ํด๋ž˜์Šค: Template method์ธ cookRamen์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • Template Method: cookRamen
    • ๋‚ด๋ถ€์ ์œผ๋กœ boilWater, addRamen, addons, wait ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • boilWater(): ๋ฌผ 550ml ๋“์ž„.
  • addRamen(): ๋ฉด, ์Šคํ”„, ํ›„๋ ˆ์ดํฌ๋ฅผ ๋„ฃ์–ด์คŒ.
  • addons(): ๊ธฐ๋ณธ ์žฌ๋ฃŒ ์ด์™ธ์˜ ์žฌ๋ฃŒ๋ฅผ ๋„ฃ๋Š” ๊ฒƒ์ธ๋ฐ ๊ธฐ๋ณธ ๋ผ๋ฉด์ด๋ฏ€๋กœ pass.
  • wait(): 4๋ถ„ 30์ดˆ ๋™์•ˆ ๋“์—ฌ์คŒ.

 

basicRecipe = BasicRamenRecipe()
basicRecipe.cookRamen()

# ์ถœ๋ ฅ:
# boil 550ml of water
# add noodles, soup base, flakes
# cook for 4min 30s

 

 

  • BasicRamenRecipe์˜ object์ธ basicRecipe์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • Public method์ธ cookRamen() ํ˜ธ์ถœํ•˜๋ฉด ๋‚ด๋ถ€์˜ step ํ•จ์ˆ˜์ธ boilWater, addRamen, wait ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

์–‘ํŒŒ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ผ๋ฉด ๋ ˆ์‹œํ”ผ

class NocopeRecipe(BasicRamenRecipe):
    def addons(self):
        print("add onions")

 

 

  • NocopeRecipe: BasicRamenRecipe๋ฅผ ์ƒ์† ๋ฐ›์Šต๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ ๋ ˆ์‹œํ”ผ์—์„œ ์–‘ํŒŒ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฏ€๋กœ addons()๋งŒ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

 

nocopeRecipe = NocopeRecipe()
nocopeRecipe.cookRamen()

# ์ถœ๋ ฅ:
# boil 550ml of water
# add noodles, soup base, flakes
# add onions
# cook for 4min 30s

 

 

  • NocopeRecipe object์ธ nocopeRecipe๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์–‘ํŒŒ ์ถ”๊ฐ€ํ•˜๋Š” ๋ถ€๋ถ„ ์ œ์™ธํ•˜๊ณ  BasicRamenRecipe์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋ฌผ์„ ๋งŽ์ด ๋„ฃ๊ณ  ์˜ค๋ž˜ ๋“์ด๋Š” ๋ผ๋ฉด ๋ ˆ์‹œํ”ผ

class GrandmaRecipe(BasicRamenRecipe):
    def boilWater(self):
        print("boil 1000ml of water")

    def wait(self):
        print("cook for 10m")

 

 

  • GrandmaRecipe: BasicRamenRecipe๋ฅผ ์ƒ์† ๋ฐ›์Šต๋‹ˆ๋‹ค
  • ๊ธฐ๋ณธ ๋ ˆ์‹œํ”ผ์—์„œ ๋ฌผ์„ ๋งŽ์ด ๋„ฃ๊ธฐ ์œ„ํ•ด boilWater ํ•จ์ˆ˜๋ฅผ ์žฌ์ •์˜ ํ•ฉ๋‹ˆ๋‹ค.
  • 10๋ถ„ ๋™์•ˆ ๋“์ด๊ธฐ ์œ„ํ•ด wait ํ•จ์ˆ˜๋ฅผ ์žฌ์ •์˜ ํ•ฉ๋‹ˆ๋‹ค.
grammaRecipe = GrandmaRecipe()
grammaRecipe.cookRamen()

# ์ถœ๋ ฅ:
# boil 1000ml of water
# add noodles, soup base, flakes
# cook for 10m

 

 

  • GrandmaRecipe object์ธ grammaRecipe๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • boilWater()๊ณผ wait() ํ•จ์ˆ˜ ๋ถ€๋ถ„์ด ๋ณ€๊ฒฝ๋˜์—ˆ์œผ๋ฉฐ ๋‚˜๋จธ์ง€๋Š” BasicRamenRecipe์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

Template Method ํŒจํ„ด์€ Base class์—์„œ ์ œ๊ณต๋˜๋Š” Abstract methods๋ฅผ ์žฌ์ •์˜ํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.


 

๊ฐœ๋… ํ™•์žฅ

ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์˜ ์žฅ์ 

  • ๋กœ์ง์„ ๊ณตํ†ตํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒ์œ„ ํด๋ž˜์Šค์˜ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ์—์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๊ธฐ์ˆ ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ผ์ผ์ด ๊ธฐ์ˆ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ƒ์œ„ ํด๋ž˜์Šค์™€ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์—ฐ๊ณ„

  • ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์—์„œ๋Š” ์ƒ์œ„ ํด๋ž˜์Šค์™€ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๊ธด๋ฐ€ํ•˜๊ฒŒ ์—ฐ๊ณ„๋˜์–ด ์ž‘๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ์„ ์–ธ๋œ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์‹ค์ œ๋กœ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•  ๋•Œ์—๋Š” ๊ทธ ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋Š ํƒ€์ด๋ฐ์— ํ˜ธ์ถœ๋˜๋Š”์ง€ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์†Œ์Šค ํ”„๋กœ๊ทธ๋žจ์˜ ๊ธฐ์ˆ ์„ ๊ฑฐ์˜ ํ•˜์ง€ ์•Š์œผ๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ˜๋Œ€๋กœ, ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ๊ธฐ์ˆ ์„ ๋งŽ์ด ํ•˜๊ฒŒ ๋˜๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์ž์œ ๋„๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.
  • ์ฒ˜๋ฆฌ์˜ ๊ณจ๊ฒฉ์„ ์ƒ์œ„ ํด๋ž˜์Šค์—์„œ ํ•˜๊ณ , ๊ตฌ์ฒด์ ์ธ ๊ฒƒ์€ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ, ์–ด๋–ค ๋ ˆ๋ฒจ์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ๋ถ„๋ฐฐํ• ์ง€, ์–ด๋–ค ์ฒ˜๋ฆฌ๋ฅผ ์ƒ์œ„ ํด๋ž˜์Šค์— ๋‘๊ณ , ํ•˜์œ„ ํด๋ž˜์Šค์— ๋‘˜์ง€ ์ด๋Ÿฐ ๊ฒƒ๋“ค์€ ์ •ํ•ด์ง„ ๋งค๋‰ด์–ผ์ด ์—†์Šต๋‹ˆ๋‹ค -> ํ”„๋กœ๊ทธ๋žจ์„ ์„ค๊ณ„ํ•˜๋Š” ์‚ฌ๋žŒ์˜ ๋ชซ์ž…๋‹ˆ๋‹ค.

ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์ƒ์œ„ ํด๋ž˜์Šค์™€ ๋™์ผ์‹œํ•จ

  • CharDisplay, StringDisplay์˜ ์ธ์Šคํ„ด์Šค๋“ค์€ AbstractDisplay๋ฅผ ๋ถ€๋ชจ๋กœ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์œ„ ํด๋ž˜์Šค์˜ ํƒ€์ž…์ด ํŠน์ •๋˜์ง€ ์•Š์•„๋„ ํ”„๋กœ๊ทธ๋žจ์ด ์ž˜ ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • ์ƒ์œ„ ํด๋ž˜์Šค ํƒ€์ž…์˜ ๋ณ€์ˆ˜์— ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์–ด๋–ค ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋Œ€์ž…ํ•ด๋„ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์›์น™์€ ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™์„ ๋”ฐ๋ผ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.