U E D R , A S I H C RSS

Gof/Factory Method


DeleteMe ) ˜„žฌ „–‰ค‘ --ƒ๋ฏผ

1. Factory Method

1.1. Intent : ˜๋„

๊ฐฒด ƒ„„ œ„•œ ธ„Ž˜ดŠค๋ฅผ  •˜•˜๋ผ, ๊ทธ๋ ‡ง€๋งŒ sub ด๋ž˜Šค๋“คด ๊ตฌ˜„‚ฌ•ญ„ ๊ฒฐ •• ˆ˜ žˆ๋„๋ก •˜ž.

Factory Method๋Š” sub ด๋ž˜Šค— ๋Œ€•ด ๊ตฌ˜„ ‚ฌ•ญ„ ๊ฒฐ •• ˆ˜ žˆ๊ฒŒ ๋งŒ๋“ ๋‹ค.

1.2. Also Known As : ๋น„Šท•œ, ˜น€ ๋™ผ•œ —ญ• „ •˜๋Š” šฉ–ด

DeleteMe) ด๊–ด๋– ๋ƒ.

Virtual Constructor ( MoreEffectiveC++ Item 25 ฐธ๊ณ  )

1.3. Motivation : ๋™๊ธฐ

Framework(ด•˜ Framework ๊ทธ๋Œ€๋กœ)๋Š” ๊ฐฒด‚ฌด˜ ๊ด€๊ฒŒ๋ฅผ  •˜•˜๊ณ , œ ง€•˜๊ธฐ œ„•˜—ฌ ๊ฐ€ƒ ด๋ž˜Šค๋“ค„ ‚ฌšฉ•œ๋‹ค. Framework๋Š” ข…ข… ด๋Ÿฌ•œ ด๋ž˜Šค๋“ค„ ๊ธฐ๋ฐ˜œผ๋กœ ๊ฐฒด˜ ƒ„— …ž„„ „๋‹ค.

—ฌ๋Ÿฌ ๋ฌธ„œ๋ฅผ ‚ฌšฉž—๊ฒŒ ๋ณด—ฌ„ˆ˜ žˆ๋Š” –ด”Œ๋ฆฌผ€ด…˜— ๋Œ€•œ Framework— ๋Œ€•˜—ฌ ƒ๊ฐ•ด ๋ณดž. ด๋Ÿฌ•œ Framework—„œ ๋‘๊ฐ€ง€˜ ถ”ƒ™”— ๋Œ€•œ 𔠐€, Application๊ณผ Documentด๋ž˜Šค ผ๊ฒƒด๋‹ค. ด ๋‘ ด๋ž˜Šค๋‹ค ถ”ƒ ด๊ณ , ด๋ผด–ธŠธ๋Š” ๊ทธ๋“ค˜ Application— •Œ๋งž๊ฒŒ ๋ช…„‚ฌ•ญ„ ๊ตฌ˜„•ด•ผ •œ๋‹ค. ˜ˆ๋ฅผ๋“ค–ด„œ Drawing Application„ ๋งŒ๋“ค๋ ค๋ฉด šฐ๋ฆฌ๋Š” DrawingApplication ๊ณผ DrawingDocument ด๋ž˜Šค๋ฅผ ๊ตฌ˜„•ด•ผ •œ๋‹ค. Applicationด๋ž˜Šค๋Š” Document ด๋ž˜Šค๋ฅผ ๊ด€๋ฆฌ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ‚ฌšฉž๊ฐ€ Openด๋‚˜ New๋ฅผ ๋ฉ”๋‰ด—„œ „ ƒ•˜˜€„๋•Œ ด๋“ค„ ƒ„•œ๋‹ค.

Application(ด๋ž˜Šค๊ฐ€ •„๋‹˜)๋งŒ๋“ค๋•Œ š”๊ตฌ๋˜๋Š” Šน๋ณ„•œ Document— ๋Œ€•œ Sub ด๋ž˜Šค ๊ตฌ˜„๋•Œ๋ฌธ—, Application ด๋ž˜Šค๋Š” Doment˜ Sub ด๋ž˜Šค— ๋Œ€•œ ๋‚ดšฉ„ ˜ˆธก• ˆ˜๊ฐ€ —†๋‹ค. Application ด๋ž˜Šค๋Š” ˜คง ƒˆ๋กœšด ข…๋ฅ˜ Document๊ฐ€ ๋งŒ๋“ค–ด ˆ๋•Œ๊ฐ€ •„๋‹ˆ๋ผ, ƒˆ๋กœšด Document ด๋ž˜Šค๊ฐ€ ๋งŒ๋“ค–ด ˆ๋•Œ๋งŒ ด๋ฅผ ๋‹ค๋ฃฐˆ˜ žˆ๋Š” ๊ฒƒด๋‹ค. ด๋Ÿฐ ƒ„€ ๋”œ๋ ˆ๋งˆด๋‹ค.:Framework๋Š” ๋ฐ˜๋“œ‹œ ด๋ž˜Šค— ๊ด€•ด„œ ๋ช…‹œ•ด•ผ ๋˜ง€๋งŒ, ‹ค œ˜ “ฐž„„ ‘œ˜„• ˆ˜ —†๊ณ  ˜คง ถ”ƒ™”๋œ ๋‚ดšฉ ๋ฐ–— ๋‹ค๋ฅผˆ˜ —†๋‹ค.

Factory Method Œจ„€ ด— ๋Œ€•œ •ด๊ฒฐ…„  œ‹œ•œ๋‹ค. ๊ทธ๊ฒƒ€ Document˜ sub ด๋ž˜Šค˜ ƒ„— ๋Œ€•œ  •๋ณด๋ฅผ บกА™” ‹œ‚ค๊ณ , Framework˜ ™ธ๋ถ€๋กœ ด๋Ÿฐ  •๋ณด๋ฅผ ด๋™ ‹œ‚ค๊ฒŒ •œ๋‹ค.

DeleteMe ๊ทธ๋ฆผถ”๊ฐ€
fac1.gif

Application˜ Sub ด๋ž˜Šค๋Š” Applicationƒ—„œ ถ”ƒ ธ CreateDocument ˆ˜–‰„ žฌ •˜ •˜๊ณ , Document subด๋ž˜Šค—๊ฒŒ  ‘๊ทผ• ˆ˜ žˆ๊ฒŒ •œ๋‹ค. Aplication˜ subด๋ž˜Šค๋Š” •œ๋ฒˆ ๊ตฌ˜„๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹คŒ ๊ทธ๊ฒƒ€ Application— •Œ๋งž€ Document— ๋Œ€•˜—ฌ ๊ทธ๋“ค— ด๋ž˜Šค๊ฐ€ Šน๋ณ„žˆ •Œ •„š” —†ด ๊ตฌ˜„• ˆ˜ žˆ๋‹ค. šฐ๋ฆฌ๋Š” CreateDocument๋ฅผ ˜ธถœ•œ๋‹ค. ™œ๋ƒ•˜๋ฉด ๊ฐฒด˜ ƒ„— ๋Œ€•˜—ฌ ๊ด€—ฌ•˜๊ธฐ œ„•ด„œ ด๋‹ค.

1.4. Applicability :  šฉ

Fatory Method Œจ„€ ด๋Ÿด๋•Œ ‚ฌšฉ•œ๋‹ค.
  • ด๋ž˜Šค๊ฐ€ ๊ทธ๊ฒƒด ƒ„•˜๋Š” ด๋ž˜Šค— ๊ด€•ด„œ ˜ˆƒ• ˆ˜ —†„๋•Œ
  • ด๋ž˜Šค๊ฐ€ ๊ทธ๊ฒƒ˜ sub ด๋ž˜Šค๊ฐ€ ๊ฐฒด ƒ„— ตœ ™”๋ฅผ ‹œ‚ค๊ณ  ‹ถ„๋•Œ
  • ด๋ž˜Šค๊ฐ€ ๋ช‡๊ฐœ˜ helper subด๋ž˜Šค—๊ฒŒ …ž„„ œ„ž„•˜๊ฐ๋‚˜, ๋‹น‹ ด helper subด๋ž˜Šค— ๊ด€•œ  •๋ณด๋ฅผ Šน„™” ‹œ‚ค๊ธฐ๋ฅผ ›• ๋•Œ

1.5. Structure


DeleteMe ๊ตฌกฐ— ๊ด€•œ ๊ทธ๋ฆผ

1.6. Participants

  • Product (Document)
    • Factory Method๊ฐ€ ƒ„•˜๋Š” ๊ฐฒด— ๊ด€•œ ธ„Ž˜ดŠค๋ฅผ  •˜•œ๋‹ค.

  • ConcreteProduct (MyDocument)
    • Product— ธ„Ž˜ดŠค— ๋Œ€•œ ๊ตฌ˜„‚ฌ•ญด๋‹ค.

  • Creator (Application)
    • Procunt ˜•˜ ๊ฐฒด๋ฅผ ๋ฐ˜™˜•˜๋Š” Factory Method๋ฅผ „ –ธ•œ๋‹ค. Creator๋Š” ๋˜•œ ๊ธฐ๋ณธ ConcreteProduct๊ฐฒด๋ฅผ ๋ฐ˜™˜•˜๋Š” factory method— ๊ด€•œ ๊ธฐ๋ณธ ๊ตฌ˜„๋„  •˜๋˜–ด žˆ๋‹ค.
    • Product๊ฐฒด๋ฅผ ๋งŒ๋“ค๊ธฐœ„•œ factory method๋ฅผ ˜ธถœ•œ๋‹ค.

  • ConcreteCreator (MyApplication)
    • ConcreteProduct˜ ธŠค„Šค๋ฅผ ๋ฐ˜™˜•˜๊ธฐ œ„•œ, factory method๋ฅผ ˜ค๋ฒ„๋ผด๋“œ(over ride) •œ๋‹ค.

1.7. Collaborations : ˜‘๋ ฅ

Creator๋Š” factor method๊ฐ€  •˜๋˜–ด žˆ๋Š” Creator˜ subด๋ž˜Šค—๊ฒŒ ˜ง€•œ๋‹ค ๊ทธ๋ž˜„œ Creator๋Š” CooncreteProduct—  •ฉ•œ ธŠค„Šค๋“ค„ ๋ฐ˜™˜•œ๋‹ค.

1.8. Consequences : ๊ฒฐ๋ก 

DeleteMe) '๊ฒฐ๊ณผ' ๋‚˜ '๊ฒฐ๋ก ' ด๋‚˜ ๊ทธ๊ฒŒ ๊ทธ๊ง€๋งŒ. --; 'Œจ„ šฉ๊ฒฐ๊ณผ'  •๋„.
DeleteMe) ™œ ๊ฒฐ๊ณผง€. ๊ฒฐ๊ณผ๋Š”  šฉ›„— –ป„ˆ˜ žˆ๋Š” ดตดง€๋งŒ, ˜„žฌ ด๊ฒƒ€ Œจ„„  šฉ•œ ฝ”๋“œ๋ฅผ ๊ตฌ˜„•˜๊ธฐ  „— ด๋ก   ๋ฐ”ƒ•— ๋Œ€•˜—ฌ ๊ฒฐ๋ก  ง“๋Š” ๊ฒƒด๋ผ๊ณ  ƒ๊ฐ•ด„œ ๊ฒฐ๋ก ด๋ผ๊ณ  –ˆŒ. ๊ทธ๋ƒฅ ๊ฒฐ๊ณผ๋Š” ๋ถ€•œ๊ฒƒ ๊ฐ™๊ณ , "Œจ„ šฉ ๊ฒฐ๊ณผ"๋ณด๋‹ค๋Š” "Œจ„ šฉ ๊ฒฐ๊ณผ ๊ณ ฐฐ" ด๋ผ๋Š” ˜๋ฏธ๊ฐ€ ๊ฐ••œ๊ฐ ๊ฐ™€๋ฐ, ๊ทธ๋ƒฅ ๊ฒฐ๋ก œผ๋กœ ฟจ๋Ÿญ --;

Factory method๋Š” ๋‹น‹ ˜ ฝ”๋“œ—„œ ๋งŒ๋“ค–ด•ผ•œ Applicationด š”๊ตฌ•˜๋Š” ด๋ž˜Šค— ๋Œ€•œ ๊ธฐ๋Šฅ๊ณผ Framework๊ฐ€ ๋ฌถ—ฌ•ผ•  •„š”„„  œ๊•œ๋‹ค. ๊ทธ ฝ”๋“œ๋Š” ˜คง Product˜ ธ„Ž˜ดŠค ๋งŒ„  •˜•œ๋‹ค.; ๊ทธ๋ž˜„œ –ด๋– •œ ConcreteProduct˜ ด๋ž˜Šค๋ผ๋„  •˜• ˆ˜ žˆ๊ฒŒ •˜—ฌ ค€๋‹ค.

DeleteMe ๋ชจ˜ธ
factory method˜ ž žฌ ธ ๋‹จ ด๋ผ๊ณ  •œ๋‹ค๋ฉด ด๋ผด–ธŠธ๊ฐ€ •„๋งˆ๋„ ๋‹จง€ Šน๋ณ„•œ ConcreteProduct๊ฐฒด๋ฅผ ๋งŒ๋“ค๊ธฐœ„•ด„œ Creatorด๋ž˜Šค˜ subด๋ž˜Šค๋ฅผ ๊ฐ€ง€๊ณ  žˆ–ด•ผ •œ๋‹ค๋Š” ๊ฒƒผ๊บผ๋‹ค. ด๋ผด–ธŠธ๊ฐ€ –ด๋–ค ‹œผ๋กœ๋“  Creator˜ subด๋ž˜Šค๋ฅผ ๋งŒ๋“ค๋•Œ˜, subด๋ž˜Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒžฒด๋Š” ข‹๋‹ค. •˜ง€๋งŒ ด๋ผด–ธŠธ๋Š” ด๋Ÿฐ๊ฒƒ— ‹ ๊ฒฝ“ธ •„š”—†ด ๋กœง ๊ตฌ˜„— ‹ ๊ฒฝ„ จ•ผ •œ๋‹ค.

A potential disadvantage of factory methods is that clients might have to subclass the Creator class just to create a particular ConcreteProduct object. Subclassing is fine when the client has to subclass the Creator class anyway, but otherwise the client now must deal with another point of evolution.

ž, —ญ‹œ Factory Method Œจ„— ๊ด€๋ จ•œ ๋‘๊ฐ€ง€˜ ๊ฒฐ๋ก „ ด•ผ๊ธฐ •œ๋‹ค.:
Here are two additional consequences of the Factory Method pattern:

  1. „œ๋ธŒ ด๋ž˜Šค™€ †Œ†ต †ต๋กœ  œ๊ณต(Provides hooks for subclasses.) Factory Method๋ฅผ  šฉ•œ ด๋ž˜Šค—„œ ๊ฐฒด˜ ƒ„€ •ญƒ ง ‘ ๋งŒ๋“ค–ดง€๋Š” ๊ฐฒด— ๋น„•˜—ฌ œ —ฐ•˜๋‹ค. Factory Method๋Š” ๊ฐฒด˜ ƒ†๋œ ๋ฒ„ „˜  œ๊ณต„ œ„•˜—ฌ, subด๋ž˜Šค™€ —ฐ๊ฒฐ๋ ˆ˜ žˆ๋‹ค.(hook˜ ˜๋ฏธธ๋ฐ, —ฐ๊ฒฐ๋กœ •ด„–ˆ๊ณ , ๊ทธ๋ฆผ„ ๋ณด๊ณ  ด•ด•ด•ผ •œ๋‹ค.)

    Ducument— œ—„œ Documentด๋ž˜Šค๋Š” factory method— •ด๋‹น•˜๋Š”, ž๋ฃŒ๋ฅผ —ด๋žŒ•˜๊ธฐ œ„•œ ๊ธฐ๋ณธ ŒŒผ ๋‹คด–ผ๋กœ๊ทธ๋ฅผ ƒ„•˜๋Š” CreateFileDialogด ˜ธถœ„  •˜• ˆ˜ žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Document subด๋ž˜Šค๋Š” ด๋Ÿฌ•œ factory method๋ฅผ ˜ค๋ฒ„ ๋ผด๋”ฉ•ด„œ ๋งŒ๋“ค๊ณ ž •˜๋Š” application— Šน™”๋œ ŒŒผ ๋‹คด–ผ๋กœ๊ทธ๋ฅผ  •˜• ˆ˜ žˆ๋‹ค. ด๋Ÿฌ•œ ๊ฒฝšฐ— factory method๋Š” ถ”ƒ ดง€ •Š๋‹ค. •˜ง€๋งŒ ˜ฌ๋ฐ”๋ฅธ ๊ธฐ๋ณธ ๊ตฌ˜„„  œ๊ณต•œ๋‹ค.

  2. ด๋ž˜Šค ƒ† ๊ด€๊ฒŒ— ˆ˜‰ ธ(๋ณ‘๋ ฌ ธ) —ฐ๊ฒฐ  œ๊ณต(Connects parallel class hierarchies.) —ฌƒœ๊นŒง€ factory method๋Š” ˜คง Creator—„œ๋งŒ ๋ถˆ๋ฆฌ๋Š”๊ƒ๊ฐ•ด ™”๋‹ค. ๊ทธ๋ ‡ง€๋งŒ ด๋ฒˆ—๋Š” ๊ทธ๋Ÿฌ•œ ๊ฒฝšฐ๋ฅผ ๋”ฐง€๋Š” ๊ฒƒด •„๋‹ˆ๋‹ค.; ด๋ผด–ธŠธ๋Š” ˆ˜‰ (๋ณ‘๋ ฌ )ธ ด๋ž˜Šค๊ฐ„ ƒ† ๊ด€๊ณ„—„œ factory method˜ œ šฉ•จ„ ฐพ„ˆ˜ žˆ๋‹ค.

    ๋ณ‘๋ ฌ ด๋ž˜Šค ƒ†€ ด๋ž˜Šค๊ฐ€ –ด๋– •œ ๋ฌธ œ˜ …ž„— ๊ด€•ด„œ ๋‹ค๋ฅธ ด๋ž˜Šค๋กœ ๋ถ„๋ฆฌ•˜๊ณ , …ž„„ œ„ž„•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ˆ๋ก€•œ๋‹ค. กฐ •• ˆ˜ žˆ๋Š” ๊ทธ๋ฆผ ๋„˜•(graphical figures)๋“ค— ๊ด€•ด„œ ƒ๊ฐ•ด ๋ณดž.;๊ทธ๊ฒƒ€ ๋งˆšฐŠค— ˜•˜—ฌ ๋ป—„ˆ˜ žˆ๊ณ , ˜ฎ๊ฒจง€๊ณ , šŒ •๋„ •œ๋‹ค. ๊ทธ๋Ÿฌ•œ ƒ˜ธž‘šฉ— ๋Œ€•œ ๊ตฌ˜„€ –ธ œ๋‚˜ ‰ฌšด๊ฒƒ๋งŒ€ •„๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ€ žฃผ ๋Š˜–ด๋‚˜๋Š” •ด๋‹น ๋„˜•˜ ƒƒœ  •๋ณด˜ ๋ณด๊ด€๊ณผ —…๋ฐดŠธ๋ฅผ š”๊ตฌ•œ๋‹ค. ๊ทธ๋ž˜„œ ด๋Ÿฐ  •๋ณด๋Š” ƒ˜ธ ž‘šฉ•˜๋Š”, ๊ฐฒด—๋‹ค๊ฐ€ ๋ณด๊ด€ • ˆ˜๋งŒ€ —†๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ „œ๋กœ๋‹ค๋ฅธ ๊ฐฒด˜ ๊ฒฝšฐ „œ๋กœ๋‹ค๋ฅธ ƒƒœ˜  •๋ณด๋ฅผ ๋ณด๊ด€•ด•ผ • …๋ฐ ๋งด๋‹ค. ˜ˆ๋ฅผ๋“คž๋ฉด, text ๋ชจ–‘ด ๋ฐ”๋€Œ๋ฉด ๊ทธ๊ฒƒ˜ ๊ณต๋ฐ„ ๋ณ€™”‹œ‚คง€๋งŒ, Line ๋ชจ–‘„ ๋Š˜๋ฆด๋•Œ๋Š” ๋ ˜ ด๋™œผ๋กœ ๋ชจ–‘„ ๋ฐ”๊ฟ€ˆ˜ žˆ๋‹ค.

    ด๋Ÿฌ•œ  œ•œ—„œ๋Š” ๋ชจ–‘—๋”ฐ๋ผ, ๊ฐ ƒ…Œ— ๋”ฐ๋ผ ๊ฐฒด๋ฅผ ๋ถ„๋ฆฌ•˜๋Š” ๊ฒƒด ๋” ข‹„ ๊ฒƒด๊ณ , ๊ฐž •„š”๋กœ•˜๋Š” ƒƒœ๋ฅผ œ ง€ •ด•ผ•œ๋‹ค. „œ๋กœ ๋‹ค๋ฅธ ๋ชจ–‘€ „œ๋กœ๋‹ค๋ฅธ Manipulator˜ subด๋ž˜Šค๋ฅผ ‚ฌšฉ•ด„œ ›€ง—ฌ•ผ •œ๋‹ค.ด๋Ÿฌ•œ Manipulatorด๋ž˜Šค™€ ƒ†€ ๋ณ‘๋ ฌ œผ๋กœ ด๋ฃจ–ด „๋‹ค. ๋‹คŒ๊ณผ ๊ฐ™€ ๋ชจ–‘ ๊ฐ™ด ๋งด๋‹ค.

DeleteMe ๊ทธ๋ฆผ

Figureด๋ž˜Šค๋Š” CreateManipulator๋ผ๋Š”, „œ๋กœ ž‘šฉ•˜๋Š” ๊ฐฒด๋ฅผ ƒ„•ด ฃผ๋Š” factory methodด๋‹ค. Figure˜ subด๋ž˜Šค๋Š” ด ๋ฉ”†Œ๋“œ๋ฅผ ˜ค๋ฒ„๋ผด๋“œ(override)•ด„œ ๊ทธ๋“ค—๊ฒŒ •Œ๋งž๋Š” Manipulator subด๋ž˜Šค˜ ธŠค„Šค๋ฅผ (๋งŒ๋“ค–ด, )๋ฐ˜™˜•œ๋‹ค. Figure ด๋ž˜Šค๋Š” •„๋งˆ๋„ ๊ธฐ๋ณธ ManipulatorธŠค„Šค๋ฅผ (๋งŒ๋“ค–ด,) ๋ฐ˜•œ•˜๊ธฐ œ„•œ ๊ธฐ๋ณธ CreateManipulator๋ฅผ ๊ตฌ˜„–ˆ„ ๊ฒƒด๋‹ค. ๊ทธ๋ฆฌ๊ณ  Figure˜ subด๋ž˜Šค๋Š” ๊ฐ„๋‹จžˆ ด๋Ÿฌ•œ ๊ธฐ๋ณธ๊ฐ’๋“ค„ ƒ†•˜˜€๋‹ค. Figureด๋ž˜Šค ๋“ค€ ž‹ ๊ณผ ๊ด€๊ณ„—†๋Š” Manipulator๋“ค— ๋Œ€•˜—ฌ ‹ ๊ฒฝ “ธ•„š”๊ฐ€ —†๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ด๋“ค˜ ๊ด€๊ณ„๋Š” ๋ณ‘๋ ฌ ด ๋œ๋‹ค.

Factory Method๊ฐ€ ๋‘๊ฒŒ˜ ด๋ž˜Šค˜ ƒ† ๊ด€๊ณ„—„œ –ด๋–ป๊ฒŒ ด๋Ÿฌ•œ —ฐ๊ฒฐ๊ณผ •„  •˜•˜๋Š”ง€ ฃผ๋ชฉ•˜๋ผ. ๊ทธ๊ฒƒ€ „œ๋กœ ๊ณ œ ˜ ๊ธฐ๋Šฅ„ ๋ถ€—ฌ‹œ‚ค๋Š” ž‘—…„ •œ๋‹ค.

1.9. Implementation : ๊ตฌ˜„,  šฉ

Factory MethodŒจ„ด  šฉ๋ ๋•Œ ๋ฐœƒ• ˆ˜ žˆ๋Š” ๋ฌธ œ— ๊ด€•ด„œ ƒ๊ฐ•ด ๋ณดž.:

  1. ๋‘๊ฐ€ง€˜ ปค๋‹ค๋ž€ ๋ณ€ˆ˜. Factory Method Œจ„—„œ ๋‘๊ฐ€ง€˜ ค‘š”•œ ๋ณ€ˆ˜๋Š” ฒซ๋ฒˆงธ Creator ด๋ž˜Šค๊ฐ€ ๊ฐ€ƒ ด๋ž˜Šคด๊ณ , ๊ทธ๊ฒƒ˜ „ –ธ„ •˜ง€๋งŒ ๊ตฌ˜„ด •ˆ๋ ๋•Œ˜ ๊ฒฝด ๋‘๋ฒˆงธ๋กœ Creator๊ฐ€ concrete ด๋ž˜Šคด๊ณ , factor method๋ฅผ œ„•œ ๊ธฐ๋ณธ ๊ตฌ˜„„  œ๊ณต•ด•ผ •˜๋Š” ๊ฒฝšฐ. ๊ธฐ๋ณธ ๊ตฌ˜„ด  •˜๋˜–ด žˆ๋Š” ๊ฐ€ƒ ด๋ž˜Šค๋ฅผ ๊ฐ€ง€๋Š”๊ด ๊ฐ€๋Šฅ•˜ง€๋งŒ ด๊ผ๋ฐ˜ ดง€ ๋ชป•˜๋‹ค.

    ฒซ๋ฒˆงธ ๊ฒฝšฐ๋Š” ฝ”๋“œ๊ฐ€ ๊ตฌ˜„๋œ subด๋ž˜Šค๋ฅผ š”๊ตฌ•œ๋‹ค. ™œ๋ƒ•˜๋ฉด,  ๋‹น•œ ๊ธฐ๋ณธ ๊ตฌ˜„ ‚ฌ•ญด —†๊ธฐ๋•Œ๋ฌธด๋‹ค. ˜ˆƒ• ˆ˜ —†๋Š” ด๋ž˜Šค— ๊ด€•œ ฝ”๋“œ๋ฅผ ๊ตฌ˜„•œ๋‹ค๋Š” ๊ฒƒ€ ๋”œ๋ ˆ๋งˆด๋‹ค. ๋‘๋ฒˆงธ๊ฒฝšฐ—๋Š” œ —ฐ„„ œ„•ด„œ concrete Creator๊ฐ€ factory method ๋จผ € ‚ฌšฉ•ด•ผ •˜๋Š” ๊ฒฝšฐด๋‹ค. ๋‹คŒ๊ณผ ๊ฐ™€ ๊ทœน™„ ด•ผ๊ธฐ žŒ๋‹ค."„œ๋กœ ๋ถ„๋ฆฌ๋œ ˆ˜–‰ ๋ฐฉ๋ฒ•œผ๋กœ, ๊ฐฒด๋ฅผ ƒ„•˜๋ผ, ๊ทธ๋ ‡๊ฒŒ •ด„œ subด๋ž˜Šค๋“ค€ ๊ทธ๋“คด ƒ„๋ ˆ˜ žˆ๋Š” ๋ฐฉ๋ฒ•„ ˜ค๋ฒ„๋ผด๋“œ(override)• ˆ˜ žˆ๋‹ค." ด ๊ทœน™€ subด๋ž˜Šค˜ ๋””žด๋„ˆ๋“คด •„š”•˜๋‹ค๋ฉด, ๊ทธ๋“ค ๊ณ œ ˜ ๊ฐฒด— ๊ด€๋ จ•œ ๊ธฐ๋Šฅœผ๋กœ subด๋ž˜Šค ๋‹จ—๊ฒŒ ๋ฐ”๊ฟ€ˆ˜ žˆ„Œ ˜๋ฏธ•œ๋‹ค.

  2. Parameterized factory methods(๊ทธ๋Œ€๋กœ “ด๋‹ค.) Factory MethodŒจ„—„œ ๋˜ ๋‹ค๋ฅธ ๋ณ€ˆ˜๋ผ๋ฉด ๋‹ค–‘•œ ข…๋ฅ˜˜ product๋ฅผ ‚ฌšฉ• ๋•Œ ด๋‹ค. factory method๋Š” ƒ„๋œ ๊ฐฒด˜ ข…๋ฅ˜๋ฅผ ™•ธ•˜๋Š” ธž๋ฅผ ๊ฐ€ง€๊ณ  žˆ๋‹ค. ๋ชจ๋“  ๊ฐฒด— ๋Œ€•˜—ฌ factory method๋Š” •„๋งˆ Product ธ„Ž˜ดŠค๋ฅผ ๊ณตœ •  ๊ฒƒด๋‹ค. Document˜ˆ œ—„œ, Application€ •„๋งˆ๋„ ๋‹ค–‘•œ ข…๋ฅ˜˜ Document๋ฅผ ง€›•ด•ผ •œ๋‹ค. ๋‹น‹ € CreateDocument—๊ฒŒ documentƒ„‹œ ข…๋ฅ˜๋ฅผ Œ๋ณ„•˜๋Š” ธž •˜๋‚˜๋ฅผ ๋„˜๊ธด๋‹ค.

    Unidraw ๊ทธ๋ž˜”ฝ —๋””„ฐ Framework๋Š” ๋””Šคฌ—  €žฅ๋œ ๊ฐฒด˜ žฌ ƒ„„ œ„•˜—ฌ ด๋Ÿฌ•œ  ‘๊ทผ๋ฒ•„ ‚ฌšฉ•˜๊ณ  žˆ๋‹ค. Unidraw๋Š” factory method๋ฅผ ดšฉ•œ Creator ด๋ž˜Šค๊ฐ€ ‹๋ณ„ž๋ฅผ ๊ฐ€ง€๊ณ  žˆ๋„๋ก  •˜•ด ๋‘—ˆ๋‹ค. ด ด๋ž˜Šค ‹๋ณ„ž๋Š”  •ฉ•œ ด๋ž˜Šค๋ฅผ ๊ธฐˆ •˜๊ณ  žˆ๋‹ค. Unidraw๊ฐ€ ๊ฐฒด๋ฅผ ๋””Šคฌ—  €žฅ• ๋•Œ ด ด๋ž˜Šค ‹๋ณ„ž๊ฐ€ ธŠค„Šค ๋ณ€ˆ˜˜ –ด๋–ค๊ฒƒ ๋ณด๋‹ค๋„ •ž— ๊ธฐ๋ก ๋˜๋Š” ๊ฒƒด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋””Šคฌ—„œ ๋‹ค‹œ ๊ฐฒด๋“คด ƒ„๋ ๋•Œ ด ‹๋ณ„ž๋ฅผ —ญ‹œ ๊ฐ€žฅ ๋จผ € ฝ๋Š”๋‹ค.

    ด๋ž˜Šค ‹๋ณ„ž๋ฅผ ฝ๊ณ „œ Framework๋Š” ‹๋ณ„ž๋ฅผ Create—๊ฒŒ ๋„˜๊ธฐ๋ฉด„œ ˜ธถœ•œ๋‹ค. Create๋Š”  ๋‹น•œ ด๋ž˜Šค๋ฅผ ฐพ๊ณ , ๊ทธ๊ฒƒ„ ๊ฐฒด˜ ƒ„— ‚ฌšฉ•œ๋‹ค. ๋งˆง€๋ง‰œผ๋กœ Create๋Š” ๊ฐฒด˜ Read ˆ˜–‰„ ˜ธถœ•˜—ฌ ๋””Šคฌ—  •๋ณด๋ฅผ  €žฅ•˜๊ณ , ธŠค„Šค ๋ณ€ˆ˜๋“ค„ ˆ๊ธฐ™” •œ๋‹ค.

    Parameterized factory method๋Š” Product๋ฅผ ƒ†๋ฐ›€ MyProduct™€ YourProductƒ—„œผ๋ฐ˜ œผ๋กœ ๋‹คŒ๊ณผ ๊ฐ™€ ˜•ƒœ๋ฅผ ๊ฐ€„๋‹ค.
    ~cpp 
    class Creator {
    public:
        virtual Product* Create(ProductId);
    };
    
    Product* Creator::Create (ProductId id) {
        if (id == MINE)  return new MyProduct;
        if (id == YOURS) return new YourProduct;
        // ๋‚จ€ product˜ ข…๋ฅ˜˜ ๋ฐ˜๋ณต    
        return 0;
    }
    

    Parameterized factory method ๋Š” Creator๊ฐ€ ƒ„•˜๋Š” product๋ฅผ „ ƒ œผ๋กœ ™•žฅ•˜๊ณ , ๋ณ€™”‹œ‚ค๋Š”๋ฐ, ‰ฝ๊ฒŒ ๋งŒ๋“ค–ด ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ƒˆ๋กœšด ‹๋ณ„ž๋กœ ƒˆ๋กœšด ข…๋ฅ˜˜ product๋ฅผ ๋„ž…•˜๊ณ ๋‚˜, „œ๋กœ๋‹ค๋ฅธ product˜ ‹๋ณ„ž๋ฅผ —ฐ๊ด€‹œ‚ฌˆ˜๋„ žˆ๋‹ค.

    ˜ˆ๋ฅผ ๋“ค–ด„œ subด๋ž˜Šค MyCreator๋Š” MyProduct™€ YouProduct๋ฅผ ๋ฐ”๊พธ๊ณ , ƒˆ๋กœšด TheirProduct Subด๋ž˜Šค๋ฅผ ง€›• ˆ˜ žˆ๋‹ค.
    ~cpp 
    Product* MyCreator::Create (ProductId id) {
        if (id == YOURS)  return new MyProduct;
        if (id == MINE)   return new YourProduct;
            // YouProduct™€ MyProduct ๊ต™˜
        if (id == THEIRS) return new TheirProduct;  // ƒˆ๋กœšด product ถ”๊ฐ€
    
        return Creator::Create(id); // ๋งŒ•ฝ ๋ชจ๋‘๊ฐ€ ‹คŒจ•˜๋ฉด ๊ธฐ๋ณธ ƒ„ž๋ฅผ ๋ถ€๋ฅธ๋‹ค.
    }
    
    DeleteMe ๋ชจ˜ธ)๋งˆง€๋ง‰ ๋ถ€๋ถ„—„œ ๋ถ€๋ชจ ด๋ž˜Šค˜ ธž๋ฅผ ˆ˜–‰•˜๋Š” ๊ฒƒ„ ฃผ๋ชฉ•ด๋ผ. MyCreator::Create๋Š” ˜คง YOURS, MINE, THEIRS๋ฅผ žก„ˆ˜ žˆ๊ณ , ๋ถ€๋ชจด๋ž˜Šค๋Š” žกง€ ๋ชป•œ๋‹ค. ๋‹ค๋ฅธ ด๋ž˜Šค๋Š” ด๋ฅผ ˆ˜–‰•˜ง€ ๋ชป•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ, MyCreator๋Š” ƒ„๋œ product˜ •œ ข…๋ฅ˜๋ฅผ ™•žฅ•˜๊ณ , ๊ทธ๊ฒƒ€ ƒ„— ๋Œ€•œ …ž„„ —ฐ๊ธฐ•œ๋‹ค. •˜ง€๋งŒ, product๊ฐ€ ๊ทธ๊ฒƒ˜ ๋ถ€๋ชจธ๊ฒƒ€  ๋‹ค.

MyCreator::Create handles only YOURS, MINE, and THEIRS differently than the parent class. It isn't interested in other classes. Hence MyCreator extends the kinds of products created, and it defers responsibility for creating all but a few products to its parent.

  1. –ธ–ด ๊ทœน™—„œ˜ ๋ณ€ˆ˜™€ ดŠˆ(Language-specific variants and issues) ๋‹ค๋ฅธ –ธ–ด‚ฌ—„œ๋Š” ข€๋” ๋‹ค๋ฅธ ๋ฐฉ‹œผ๋กœ ๋‹ค๋ฅธ  ˆฐจ๋กœ ๊ตฌ˜„๋  ๊ฒƒด๋‹ค.

    Smalltalk”„๋กœ๊ทธ๋ž˜๋จธ๋“ค€ ข…ข… ๊ตฌฒด œผ๋กœ ๊ตฌ˜„๋˜–ด žˆ๋Š” ๊ฐฒด˜ ด๋ž˜Šค๋ฅผ ๋ฐ˜™˜•˜๋Š” ๋ฉ”†Œ๋“œ๋ฅผ ‚ฌšฉ•œ๋‹ค. Creator˜ factory method๋Š” ด๋Ÿฌ•œ ๊ฐ’„ ‚ฌšฉ•˜—ฌ product๋ฅผ ๋งŒ๋“ค–ด ๋‚ด๊ณ , ConcreteCreator๋Š” •„๋งˆ  €žฅ•˜๊ฐ๋‚˜, ด๋Ÿฌ•œ ๊ฐ’œผ ๊ณ„‚ฐ„ ˆ˜–‰•œ๋‹ค. ด๋Ÿฌ•œ ๊ฒฐ๊ณผ๋Š” ๊ตฌ˜„๋˜–ด žˆ๋Š” ConcreteProduct˜ ˜•„ œ„•˜—ฌ ๋ฐ”ธ๋”ฉ กฐฐจ ๋‚˜ค‘— •˜๊ฒŒ ๋œ๋‹ค.

    Smalltalk ๋ฒ„ „˜ Document ˜ˆ œ๋Š” documentClass ๋ฉ”†Œ๋“œ๋ฅผ Applicationƒ—  •˜• ˆ˜ žˆ๋‹ค. documentClass ๋ฉ”†Œ๋“œ๋Š” ž๋ฃŒ๋ฅผ ‘œ˜„•˜๊ธฐ œ„•œ  ๋‹น•œ Document ด๋ž˜Šค๋ฅผ ๋ฐ˜™˜•œ๋‹ค. MyApplication—„œ documentClass˜ ๊ตฌ˜„€ MyDocument ด๋ž˜Šค๋ฅผ ๋ฐ˜™˜•˜๋Š” ๊ฒƒด๋‹ค. ๊ทธ๋ž˜„œ Applicationƒ˜ ด๋ž˜Šค๋Š” ด๋ ‡๊ฒŒ ƒ๊ฒผ๊ณ 
    ~cpp 
        clientMethod
            document := self documentClass new.
        
        documentClass
            self subclassResponsibility
    

MyApplication ด๋ž˜Šค๋Š” MyDocumentด๋ž˜Šค๋ฅผ ๋ฐ˜™˜•˜๋Š” ๊ฒƒœผ๋กœ ๊ตฌ˜„๋œ๋‹ค.

~cpp 
    documentClass
        ^ MyDocument

๋” œ —ฐ•œ  ‘๊ทผ ๋ฐฉ‹€ ๋น„Šท•˜๊ฒŒ parameterized factory method Application˜ ด๋ž˜Šค˜ ๋ณ€ˆ˜๋“ค๊ณผ ๊ฐ™ด ƒ„๋˜–ดง€๋Š” ด๋ž˜Šค๋ฅผ ๋ณด๊ด€•˜๋Š” ๊ฒƒด๋‹ค.๊ทธ๋Ÿฌ•œ ๋ฐฉ‹€ product๋ฅผ ๋ณ€๊ฒฝ•˜๋Š” Application„ ๋ฐ˜๋“œ‹œ ๊ฐ‹ธ•ผ •œ๋‹ค.

C++—„œ Factory method๋Š” •ญƒ ๊ฐ€ƒ•จˆ˜ด๊ณ , ข…ข… ˆœˆ˜ ๊ฐ€ƒ •จˆ˜ด๋‹ค. Creator˜ ƒ„ž ๋‚ด๋ถ€—„œ factory methods˜ ˜ธถœ€ ๊ฒฐฝ” ข‹ง€ ๋ชป•œ๊ฒƒ ผ๊นŒ? ๊ทธ๋Ÿฌ•œ factory method๋Š” ConcreteCreator•ˆ— กดžฌ•˜๊ณ , •„ง ™œ„™” ๋˜ง€ •Š•˜๋‹ค.

You can avoid this by being careful to access products solely through accessor operations that create the product on demand. Instead of creating the concrete product in the constructor, the constructor merely initializes it to 0. The accessor returns the product. But first it checks to make sure the product exists, and if it doesn't, the accessor creates it. This technique is sometimes called lazy initialization. The following code shows a typical implementation:

~cpp 
    class Creator {
    public:
        Product* GetProduct();
    protected:
        virtual Product* CreateProduct();
    private:
        Product* _product;
    };
    
    Product* Creator::GetProduct () {
        if (_product == 0) {
            _product = CreateProduct();
        }
        return _product;
    }


  1. Using templates to avoid subclassing. As we've mentioned, another potential problem with factory methods is that they might force you to subclass just to create the appropriate Product objects. Another way to get around this in C++ is to provide a template subclass of Creator that's parameterized by the Product
    ~cpp 
    class: 
        class Creator {
        public:
            virtual Product* CreateProduct() = 0;
        };
        
        template 
        class StandardCreator: public Creator {
        public:
            virtual Product* CreateProduct();
        };
        
        template 
        Product* StandardCreator::CreateProduct () {
            return new TheProduct;
        }
    

With this template, the client supplies just the product classno subclassing of Creator is required.

~cpp 
    class MyProduct : public Product {
    public:
        MyProduct();
        // ...
    };
    
    StandardCreator myCreator;

  1. Naming conventions. It's good practice to use naming conventions that make it clear you're using factory methods. For example, the MacApp Macintosh application framework App89 always declares the abstract operation that defines the factory method as Class* DoMakeClass(), where Class is the Product class.

1.10. Sample Code

The function CreateMaze (page 84) builds and returns a maze. One problem with this function is that it hard-codes the classes of maze, rooms, doors, and walls. We'll introduce factory methods to let subclasses choose these components.

First we'll define factory methods in MazeGame for creating the maze, room, wall, and door objects:

~cpp 
    class MazeGame {
    public:
        Maze* CreateMaze();
    
    // factory methods:
    
        virtual Maze* MakeMaze() const
            { return new Maze; }
        virtual Room* MakeRoom(int n) const
            { return new Room(n); }
        virtual Wall* MakeWall() const
            { return new Wall; }
        virtual Door* MakeDoor(Room* r1, Room* r2) const
            { return new Door(r1, r2); }
    };

Each factory method returns a maze component of a given type. MazeGame provides default implementations that return the simplest kinds of maze, rooms, walls, and doors.

Now we can rewrite CreateMaze to use these factory methods:

~cpp 
    Maze* MazeGame::CreateMaze () {
        Maze* aMaze = MakeMaze();
    
        Room* r1 = MakeRoom(1);
        Room* r2 = MakeRoom(2);
        Door* theDoor = MakeDoor(r1, r2);
    
        aMaze->AddRoom(r1);
        aMaze->AddRoom(r2);
    
        r1->SetSide(North, MakeWall());
        r1->SetSide(East, theDoor);
        r1->SetSide(South, MakeWall());
        r1->SetSide(West, MakeWall());
    
        r2->SetSide(North, MakeWall());
        r2->SetSide(East, MakeWall());
        r2->SetSide(South, MakeWall());
        r2->SetSide(West, theDoor);
    
        return aMaze;
    }

Different games can subclass MazeGame to specialize parts of the maze. MazeGame subclasses can redefine some or all of the factory methods to specify variations in products. For example, a BombedMazeGame can redefine the Room and Wall products to return the bombed varieties:

~cpp 
    class BombedMazeGame : public MazeGame {
    public:
        BombedMazeGame();
    
        virtual Wall* MakeWall() const
            { return new BombedWall; }
    
        virtual Room* MakeRoom(int n) const
            { return new RoomWithABomb(n); }
    };

An EnchantedMazeGame variant might be defined like this:

~cpp 
    class EnchantedMazeGame : public MazeGame {
    public:
        EnchantedMazeGame();
    
        virtual Room* MakeRoom(int n) const
            { return new EnchantedRoom(n, CastSpell()); }
    
        virtual Door* MakeDoor(Room* r1, Room* r2) const
            { return new DoorNeedingSpell(r1, r2); }
    protected:
        Spell* CastSpell() const;
    };

1.11. Known Uses

Factory methods pervade toolkits and frameworks. The preceding document example is a typical use in MacApp and ET++ WGM88. The manipulator example is from Unidraw.

Class View in the Smalltalk-80 Model/View/Controller framework has a method defaultController that creates a controller, and this might appear to be a factory method Par90. But subclasses of View specify the class of their default controller by defining defaultControllerClass, which returns the class from which defaultController creates instances. So defaultControllerClass is the real factory method, that is, the method that subclasses should override.

A more esoteric example in Smalltalk-80 is the factory method parserClass defined by Behavior (a superclass of all objects representing classes). This enables a class to use a customized parser for its source code. For example, a client can define a class SQLParser to analyze the source code of a class with embedded SQL statements. The Behavior class implements parserClass to return the standard Smalltalk Parser class. A class that includes embedded SQL statements overrides this method (as a class method) and returns the SQLParser class.

The Orbix ORB system from IONA Technologies ION94 uses Factory Method to generate an appropriate type of proxy (see Proxy (207)) when an object requests a reference to a remote object. Factory Method makes it easy to replace the default proxy with one that uses client-side caching, for example.

1.12. Related Patterns

Abstract Factory (87) is often implemented with factory methods. The Motivation example in the Abstract Factory pattern illustrates Factory Method as well.

Factory methods are usually called within Template Methods (325). In the document example above, NewDocument is a template method.

Prototypes (117) don't require subclassing Creator. However, they often require an Initialize operation on the Product class. Creator uses Initialize to initialize the object. Factory Method doesn't require such an operation.

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:18
Processing time 0.0484 sec