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.0680 sec