Skip to content

Latest commit

Β 

History

History
153 lines (121 loc) Β· 12.7 KB

File metadata and controls

153 lines (121 loc) Β· 12.7 KB

챕터12 λ””μžμΈ νŒ¨ν„΄

λ””μžμΈ νŒ¨ν„΄μ€ λ˜ν’€μ΄λ˜λŠ” λ¬Έμ œλ“€μ— λŒ€ν•œ 일반적이고 μž¬μ‚¬μš©κ°€λŠ₯ν•œ 해결책이닀. 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ˜ μ „ν˜•μ μΈ νŠΉμ§•μΈ λ””μžμΈ νŒ¨ν„΄μ€ μžλ°”μ™€ 루비 μ„Έκ³„μ˜ λ§Žμ€ μ΄λ“€μ—κ²Œ μΉœμˆ™ν•œ κ³΅ν†΅λœ μš©μ–΄λ₯Ό μ œκ³΅ν•œλ‹€.

λ‹€λ₯΄κ²Œ 보면, νŒ¨ν„΄μ€ μž₯황함과 λ˜ν’€μ΄μ˜ μ›μ²œμΌ μˆ˜λ„ μžˆλ‹€. 이 점에 λŒ€ν•΄μ„œ, 폴 κ·Έλ ˆμ΄μ—„μ€ μ–΄λ–€ μ–Έμ–΄μ—μ„œ λ””μžμΈ νŒ¨ν„΄μ˜ μ‘΄μž¬μ™€ μ‚¬μš©μ€ 문제λ₯Ό μ†μ‰½κ²Œ ν‘Ό 결둠이라기 보닀 κ·Έ μ–Έμ–΄ μžμ²΄μ— λŒ€ν•œ 약점을 λ‚˜νƒ€λ‚΄λŠ” 것이라고 ν‰ν•œ λ°” μžˆλ‹€.

λ‚΄κ°€ λ‚΄ ν”„λ‘œκ·Έλž¨μ—μ„œ νŒ¨ν„΄μ„ λ³Ό λ•Œ, λ‚˜λŠ” 그것이 문제의 μ§•ν‘œλΌκ³  μƒκ°ν•œλ‹€. ν”„λ‘œκ·Έλž¨μ˜ ν˜•μƒμ€ μ˜€λ‘œμ§€ ν’€μ–΄μ•Ό ν•  λ¬Έμ œλ§Œμ„
λ°˜μ˜ν•΄μ•Ό ν•œλ‹€. μ½”λ“œμ— μžˆλŠ” μ–΄λ–€ λ‹€λ₯Έ κ·œμΉ™μ„±λ„ 적어도 λ‚˜μ—κ²ŒλŠ” λ‚΄κ°€ μΆ©λΆ„νžˆ κ°•λ ₯ν•˜μ§€ μ•Šμ€ 좔상성을 μ‚¬μš©ν•˜κ³  μžˆλ‹€λŠ” μ§•ν‘œμ΄λ‹€.
                                               -- 폴 κ·Έλ ˆμ΄μ—„, http://www.paulgraham.com/icad.html

κ·Έλ ˆμ΄μ—„μ€ 이것을 μ•Œμ•„μ±ˆ 첫번째 μ‚¬λžŒμ€ μ•„λ‹ˆμ—ˆλ‹€. μ–Όλ§ˆ 전에 ν”Όν„° 노빅은 Lisp이 특히 λŒ€λΆ€λΆ„μ˜ λ””μžμΈ νŒ¨ν„΄μ„ λ‹¨μˆœν™”ν•˜κ±°λ‚˜ 보이지 μ•Šκ²Œ λ§Œλ“ λ‹€κ³  μ†Œκ°œν–ˆλ‹€.(http://www.novig.com/design-patterns/) ν΄λ‘œμ €λŠ” 이 전톡을 μ§€μ†ν•œλ‹€. 일급 ν•¨μˆ˜, 동적 타이핑, 그리고 λΆˆλ³€ κ°’λ“€ 같은 κ°•λ ₯ν•œ 생성물 덕뢄에, κ°€μž₯ 일반적인 λ””μžμΈ νŒ¨ν„΄λ“€μ˜ λ§Žμ€ 것듀이 μ†Œλ©Έλœλ‹€. 그리고, ν΄λ‘œμ €λŠ” μ—¬λŸ¬λΆ„μ—κ²Œ μ—¬λŸ¬λΆ„μ΄ 슀슀둜 μƒμš©κ΅¬λ₯Ό λ§Œλ“œλŠ” 것을 ν”Όν•˜λŠ”λ° ν•„μš”ν•œ 도ꡬ듀을 λ§€ν¬λ‘œμ™€ ν•¨κ»˜ μ œκ³΅ν•œλ‹€.

일반적인 λ‹€μžμΈ νŒ¨ν„΄λ“€μ„ ν¬κ΄„ν•˜λŠ” ν΄λ‘œμ € μ½”λ“œ μ˜ˆμ œλ“€μ€ 이 μ±… μ „λ°˜μ— 걸쳐 흩어져 μžˆλ‹€.

Listener, Observer. 일급 ν•¨μˆ˜μ™€ 동적 νƒ€μ΄ν•‘μ˜ ν¬μƒλŸ‰μΈ 이듀은 κ·Έμ € κ΄€λ ¨λœ μ΄λ²€νŠΈκ°€ λ°œμƒν•  λ•Œ ν˜ΈμΆœλ˜λŠ” ν•¨μˆ˜λ“€μ΄λ‹€. 이런 μ΄λ²€νŠΈλŠ” 176νŽ˜μ΄μ§€μ˜ "κ°μ‹œ"에 μžˆλŠ” λ ˆνΌλŸ°μŠ€λ“€ νƒ€μž…λ“€μ— λŒ€ν•œ κ°μ‹œμžλ‘œ 관찰될 μˆ˜λ„ μžˆλ‹€. 레퍼런슀 νƒ€μž…λ“€ 이외에, λΆˆλ³€ κ°’μ˜ μš°μ„ μ μΈ μ‚¬μš©μ€ μ—¬λŸ¬λΆ„μ΄ 좔적할 ν•„μš”κ°€ μžˆλŠ” 가변적인 κ²ƒλ“€μ˜ λ²”μ£Όκ°€ ꡉμž₯히 μ΅œμ†Œν™”λœλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€.

Abstract Factory, Strategy, Command. λ§Œμ•½ μ—¬λŸ¬λΆ„μ΄ μ–΄λ–€ μœ ν˜•μ˜ κΈ°λŠ₯의 κ΅¬ν˜„μ²΄λ“€μ„ μ—¬λŸ¬κ°œ κ°€μ§€κ³  μžˆλ‹€λ©΄--λ‹¬λΌμ§€λŠ” νƒ€μž…μ΄λ‚˜ μ„€μ •μ˜ 값을 μƒμ‚°ν•˜λ˜μ§€, μ•„λ‹ˆλ©΄ μ•Œκ³ λ¦¬μ¦˜μ˜ λ³€ν™”λ₯Ό κ΅¬ν˜„ν•˜λ˜μ§€ 상관없이--FactoryFactoryλ‚˜ μ—¬λŸ¬λΆ„μ˜ μ•Œκ³ λ¦¬μ¦˜ κ΅¬ν˜„μ²΄λ₯Ό ν˜ΈμΆœν•˜κΈ° μœ„ν•œ λ§₯락을 생산할 ν•„μš”κ°€ μ—†λ‹€. 두 κ°€μ§€ 경우 λͺ¨λ‘, κ·Έλƒ₯ λ‹€λ₯Έ ν•¨μˆ˜κ°€ ν•  것이닀.

Iterator. IteratorλŠ” 89νŽ˜μ΄μ§€μ˜ "μ‹œν€€μŠ€"μ—μ„œ μ„€λͺ…λœ μ‹œν€€μŠ€μ— μ˜ν•˜μ—¬ μ™„μ „νžˆ ν¬κ΄„λœλ‹€(be supersetted), κ·Έλž˜μ„œ IteratorλŠ” map 같은 ν•¨μˆ˜λ“€μ„ ν†΅ν•˜μ—¬ 적은 λ…Έλ ₯으둜 μ„ μ–Έμ μœΌλ‘œ μ‚¬μš©λœλ‹€.

Adapter, Wrapper, Delegate. λ‹€λ₯Έ κ³³μ—μ„œ 이듀은 μœ μ—°ν•˜μ§€ μ•Šμ€ νƒ€μž… 계측ꡬ쑰 λ•Œλ¬Έμ— ν•„μš”μ„±μ΄ μƒκΈ°λŠ”λ°, ν”„λ‘œν† μ½œμ΄ 이듀을 ν•„μš”μ—†κ²Œ λ§Œλ“ λ‹€. ν”„λ‘œν† μ½œμ€ μ—¬λŸ¬λΆ„μ΄ μƒμ†μ΄λ‚˜ adaptaionμ΄λ‚˜ λž˜ν•‘μ— ν˜Έμ†Œν•˜μ§€ μ•Šκ³ λ„ κΈ°μ‘΄ νƒ€μž…μ— μƒˆλ‘œμš΄ 행동을 λ³„λ„λ‘œ μ •μ˜ν•˜κ²Œ ν•΄μ€€λ‹€.

Memento. 객체의 κ°€λ³€μ„± μœ„μ— κ³΅ν†΅λœ APIλ₯Ό κ³„μΈ΅ν™”ν•˜λŠ” 것은 λ¬Έμ œλ“€μ˜ κ°€μž₯ 기계적인 뢀뢄을 ν•΄κ²°ν•˜μ§€λ§Œ(API μΌλ°˜ν™”), κ°€λ³€ μƒνƒœ 자체의 λ‘λ“œλŸ¬μ§„ λ³΅μž‘μ„±μ„ ν•΄κ²°ν•˜μ§€λŠ” λͺ»ν•œλ‹€. λΆˆλ³€ μ»¬λ ‰μ…˜κ³Ό λ ˆμ½”λ“œλ“€μ€ 이 μ „λž΅μ„ λ’€μ§‘μ—ˆλ‹€. κ°€λ³€ μƒνƒœλŠ” κ°’μ—μ„œ μ œμ™Έλ˜κ³ , κ·Έ κ°’λ“€μ˜ 이전 버전듀을 λ³΄κ΄€ν•˜λŠ” 것은 λΉ„μš©μ΄ 적게 λ“€κ³  μ‰¬μš°λ©°, μƒνƒœ λ³€ν™”λŠ” 레퍼런슀 νƒ€μž…μ— 남겨 μ§„λ‹€.(각각의 레퍼런슀 νƒ€μž…μ€ 각각의 λ™μ‹œμ„±κ³Ό λ³€ν™” μ˜λ―Έλ‘ μ— μ ν•©ν•œ λ‹€λ₯Έ APIλ₯Ό μ œκ³΅ν•œλ‹€.)

Template Method. 클래슀 μƒμ†μ˜ μ œν•œμ€ 잘 μ•Œλ €μ Έ 있으며 맀일 수천만 λͺ…이 λŠλΌμ§€λ§Œ, 클래슀 상속은 λ§Žμ€ μ–Έμ–΄λ“€μ—μ„œ κΈ°λŠ₯을 μ‘°ν•©ν•˜λŠ” μœ μΌν•œ λ°©λ²•μœΌλ‘œ λΉˆλ²ˆν•˜κ²Œ μ•„μ§κΉŒμ§€ 널리 μ‚¬μš©λœλ‹€. 이 미심쩍은 κ΄€μ‹¬μ˜ ν˜Όν•©μ€ κ³ μ°¨ ν•¨μˆ˜λ‘œ 더 잘 μž¬κ΅¬μ„±λœλ‹€. κ³ μ°¨ ν•¨μˆ˜λŠ” λ‹€μ–‘ν•œ ν–‰μœ„λ₯Ό κ΅¬ν˜„ν•˜λŠ” 것과 λ™μ‹œμ— 곡유된 κΈ°λŠ₯의 κ·œλ²”μ μΈ κ΅¬ν˜„μ„ μ œκ³΅ν•˜λŠ” ν•¨μˆ˜λ“€μ„ μˆ˜μš©ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄, μš°λ¦¬κ°€ λ§Œμ•½ μ–΄λ–€ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄λΆ€μ˜ 데이터 ꡬ쑰에 κΈ°λ°˜ν•œ λ‹€λ₯Έ κ³΅κΈ‰μžλ“€μ΄ μ œκ³΅ν•˜λŠ” λ™μΌν•œ HTTP API듀을 호좜 κ°€λŠ₯ν•˜κ²Œ λ˜λŠ” 것이 ν•„μš”ν•˜λ‹€λ©΄, κ³ μ°¨ ν•¨μˆ˜κ°€ κ³΅κΈ‰μžμ— νŠΉν™”λœ κΈ°λŠ₯을 λ³„λ„μ˜ ν•¨μˆ˜λ‘œ μ •μ˜ν•˜κ²Œ ν•΄μ£Όλ©°, λ™μ‹œμ— λ²”μš© HTTP 배관을 ν•œ κ³³μ—μ„œ μœ μ§€ν•œλ‹€.

(defn- update-status*
    [service-name service-endpoint-url request-data-fn]
    (fn [new-status]
        (log (format "Updating status @ %s to %s" service-name new-status))
        (let [http-request-data (request-data-fn new-status)
            connection (-> service-endpoint-url java.net.URL. .openConnection)]
            ;; ...set request method, parameters, body on `connection`
            ;; ...perform actual request
            ;; ...return result based on HTTP response status
)))
(def update-facebook-status (update-status* "Facebook" "http://facebook.com/apis/..."
                                (fn [status]
                                    {:params {:_a "update_status"
                                              :_t status}
                                     :method "GET"})))
(def update-twitter-status ...)
(def update-google-status ...)

λ‹€λ₯Έ κ³΅ν†΅λœ νŒ¨ν„΄λ“€μ„ μ’€ 더 μžμ„Ένžˆ νŒŒλ³΄λ„λ‘ ν•˜μž. κ·Έ νŒ¨ν„΄λ“€ 쀑 μΌλΆ€λŠ” μ§€κΈˆ λ‹€λ₯Έ μ–Έμ–΄λ“€μ—μ„œ 보편적인 ν”„λ‘œκ·Έλž˜λ° μ—°μŠ΅μœΌλ‘œ κ·Έλ ‡κ²Œ κ΅¬μ›Œμ§€λŠ”λ°, 그듀을 λ‹€μ‹œ μ„ λ³„ν•˜λŠ”λ°λŠ” μΆ”κ°€ μž‘μ—…μ΄ ν•„μš”ν•  수 μžˆλ‹€.

Dependency Injection

λ§Žμ€ 객체 μ§€ν–₯ μ–Έμ–΄λ“€μ—μ„œ, μ˜μ‘΄μ„± μ£Όμž…μ€ κ·Έ ν΄λž˜μŠ€κ°€ μ˜μ‘΄ν•˜κ³  μžˆλŠ” λ‹€λ₯Έ κ°μ²΄λ‘œλΆ€ν„° 클래슀λ₯Ό λΆ„λ¦¬ν•˜λŠ” 방법이닀. 객체가 λ‹€λ₯Έ 객체듀을 λ‚΄λΆ€μ μœΌλ‘œ μ΄ˆκΈ°ν™”ν•˜λŠ” λŒ€μ‹ μ—, κ°μ²΄λŠ” κ·Έλ“€ 객체듀을 인수둜써 받아듀인닀. κ·Έλ“€ μΈμˆ˜λŠ” μ’…μ’… μ‹€ν–‰ μ‹œκ°„μ— νž˜λ“€μ΄μ§€ μ•Šκ³  μˆœμ‹κ°„μ— μ œκ³΅λ˜κ±°λ‚˜ μ—¬λŸ¬λΆ„μ˜ ν”„λ‘œκ·Έλž¨μ„ ν˜ΈμŠ€νŒ…ν•˜λŠ” μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ»¨ν…Œμ΄λ„ˆμ— μ˜ν•΄ μˆœμ‹κ°„μ— μ œκ³΅λœλ‹€.

μžλ°” 같은 μ •μ μ–Έμ–΄μ—μ„œ, 이것은 콘크리트 클래슀 λ³΄λ‹€λŠ” μΈν„°νŽ˜μ΄μŠ€λ‘œ μž‘μ„±ν•˜λŠ” 것에 μ˜ν•΄ μ„±μ·¨λœλ‹€. 이 κ΅¬ν˜„μ„ μœ λΉ„μΏΌν„°μŠ€ 애완동물 κ°€κ²Œ μ»¨μ…‰μœΌλ‘œ μƒκ°ν•΄λ³΄μž.

interface IDog {
    public String bark();
}

class Chihuahua implements IDog {
    public String bark() {
        return "Yip!";
    }
}

class Mastiff implements IDog {
    public String bark() {
        return "Woof!";
    }
}

class PetStore {
    private IDog dog;
    public PetStore() {
        this.dog = new Mastiff();
    }
}

public IDog getDog() {
    return dog;
}

static class MyApp {
    public static void main(String[] args) {
        PetStore store = new PetStore();
        System.out.println(store.getDog().bark());
    }
}

우리의 애완동물 κ°€κ²ŒλŠ” λ§ˆμŠ€ν‹°ν”„λ§Œ μ·¨κΈ‰ν•œλ‹€. λ§Œμ•½ μš°λ¦¬κ°€ λ‹€λ₯Έ μ’…λ₯˜μ˜ κ°œλ“€μ„ μ·¨κΈ‰ν•˜κ²Œ κ°€κ²Œλ₯Ό λ°”κΎΈκ³  μ‹Άλ‹€λ©΄, μš°λ¦¬λŠ” PetStroe 클래슀λ₯Ό κ³ μ³μ„œ λ‹€μ‹œ μ»΄νŒŒμΌν•΄μ•Όλ§Œ ν•œλ‹€. PetStoreλ₯Ό μ’€ 더 μž¬μ‚¬μš©κ°€λŠ₯ν•˜κ²Œ λ§Œλ“€λ €λ©΄, PetStoreλ₯Ό λ‹€μŒ 처럼 μž¬μž‘μ„±ν•  수 μžˆλ‹€.

class PetStore {
    private IDog dog;
    public PetStore(IDog dog) {
        this.dog = dog;
    }
    public IDog getDog() {
        return dog;
    }
}

class MyApp {
    public static void main(String[] args) {
        PetStore store = new PetStore(new Chihuahua());
        System.out.println(store.getDog().bark());
    }
}

이제 κ°€κ²Œμ˜ 개 μ’…λ₯˜λŠ” μΈμˆ˜ν™” λ˜μ—ˆλ‹€. νŠΉμ • μœ ν˜•μ˜ κ°œλŠ” PetStore에 μƒμ„±μžλ₯Ό 톡해 "μ£Όμž…"λœλ‹€. PetStoreλŠ” μš°λ¦¬κ°€ λ‹€λ₯Έ 개λ₯Ό μ·¨κΈ‰ν•˜κ³  싢을 λ•Œ λ§ˆλ‹€ λ‹€μ‹œ μ»΄νŒŒμΌν•  ν•„μš”κ°€ 없을 것이닀. 심지어 μš°λ¦¬λŠ” PetStoreκ°€ μž‘μ„±λ  λ•Œ μ‘΄μž¬ν•˜μ§€ μ•Šμ•˜λ˜ ν΄λž˜μŠ€λ“€κ³Ό ν•¨κ»˜ PetStoreλ₯Ό μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€. 단지 IDog μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κΈ°λ§Œ ν•˜λ©΄ λλ‚œλ‹€. 이것은 예λ₯Ό λ“€μ–΄, μš°λ¦¬κ°€ μ‰½κ²Œ ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ Mock 개 νƒ€μž…λ“€μ„ μƒμ„±ν•˜κ²Œ ν•΄μ€€λ‹€. μ˜μ‘΄μ„± μ£Όμž…μ€ 보톡 μ»¨ν…Œμ΄λ„ˆμ— μ˜ν•΄ 이루어진닀. μ»¨ν…Œμ΄λ„ˆλŠ” μ‹€ν–‰μ‹œκ°„ 섀정을 μ‚¬μš©ν•˜μ—¬ κ·Έ 클래슀 κ²½λ‘œμ—μ„œ μžλ™μ μœΌλ‘œ λ°œκ²¬λ˜κ±°λ‚˜ κ·Έ 섀정에 λͺ…μ‹œλœ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„μ²΄λ“€κ³Ό ν•¨κ»˜ ν‚€ 객체듀을 μžλ™μ μœΌλ‘œ μ΄ˆκΈ°ν™”ν•œλ‹€. μ‹€ν–‰ μ‹œκ°„ 섀정이 μ—¬λŸ¬λΆ„μ΄ ν•¨κ»˜ μž‘μ—…ν•˜λŠ” μ»¨ν…Œμ΄λ„ˆ κ΅¬ν˜„μ²΄μ— μ˜μ‘΄ν•  λ•Œ, 이 섀정은 보톡 λ³„λ„λ‘œ κ΄€λ¦¬λ˜λŠ” μ„€μ • μ½”λ“œμ˜ μ§‘ν•© λ˜λŠ” XML νŒŒμΌλ“€μ˜ ν˜•νƒœλ₯Ό μ·¨ν•œλ‹€. ν΄λ‘œμ €λŠ” 이 문제λ₯Ό λ’€μ§‘λŠ”λ‹€. barkκ°€ μžλ°”μ—μ„œλŠ” 우리의 IDog ν΄λž˜μŠ€μ— μ˜ν•΄ μ •μ˜λœ λ©”μ„œλ“œμΈ 것에 λΉ„ν•˜μ—¬, ν΄λ‘œμ € μ½”λ“œλŠ” barkλ₯Ό μ–΄λ–€ 콘크리트 νƒ€μž…λ“€λ‘œλΆ€ν„° λΆ„λ¦¬λœ ν”„λ‘œν† μ½œ λ©”μ„œλ“œλ‘œ μ •μ˜ν•œλ‹€.

(defprotocol Bark
    (bark [this]))
    
(defrecord Chihuahua [weight price]
    Bark
    (bark [this] "Yip!"))

(defrecord Mastiff []
    Bark
    (bark [this] "Woof!"))

이제, 우리의 애완동물 κ°€κ²ŒλŠ” λ‹€μŒ 처럼 보이게 될 것이닀.

(defrecord PetStore [dog])

(defn main
    [dog]
    (let [store (PetStore. dog)]
    (println (bark (:dog store)))))
    
(main (Chihuahua.))
;= Yip!
(main (Mastiff.))
;= Woof!

그래, λ°”λ‘œ 이거닀! PetStore은 이제 ν•œ μ€„μ§œλ¦¬ μ½”λ“œκ°€ λœλ‹€.