Item 18. Composition

์ƒ์†๋ณด๋‹ค ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ

** ์ด๋ฒˆ ์•„์ดํ…œ์—์„œ ๋…ผํ•˜๋Š” ๋ฌธ์ œ๋Š” ํด๋ž˜์Šค๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•  ๋•Œ์™€๋Š” ๋ฌด๊ด€ํ•œ ๋ฌธ์ œ๋“ค์„ ๋‹ค๋ฃธ

์ƒ์†์€ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์œ ์šฉํ•œ ๋„๊ตฌ์ด์ง€๋งŒ, ํ•ญ์ƒ ์ตœ์„ ์ด ์•„๋‹ˆ๋ฉฐ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๊ฒŒ๋˜๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋‚ด๊ธฐ ์‰ฝ๊ฒŒ ๋œ๋‹ค. ์•„๋ž˜์˜ ๊ฒฝ์šฐ์—๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์•ˆ์ „ํ•˜๋‹ค.

  • ์ƒ์œ„ ํด๋ž˜์Šค์™€ ํ•˜์œ„ ํด๋ž˜์Šค ๋ชจ๋‘ ๋™์ผํ•œ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ํ†ต์ œํ•˜๋Š” ํŒจํ‚ค์ง€ ์•ˆ์—์„œ๋งŒ ์‚ฌ์šฉ

  • ํ™•์žฅํ•  ๋ชฉ์ ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๊ณ  ๋ฌธ์„œํ™”๋„ ์ž˜ ๋˜์–ด์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ๊ฒฝ์šฐ

ํ•˜์ง€๋งŒ ๋ฐ˜๋Œ€์˜ ์ƒํ™ฉ(ํŒจํ‚ค์ง€ ๊ฒฝ๊ณ„๋ฅผ ๋„˜๊ฑฐ๋‚˜, ๋ฌธ์„œํ™”๊ฐ€ ๋ถ€์กฑํ•˜๊ฑฐ๋‚˜, ํ™•์žฅ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์€ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ๊ฒฝ์šฐ)์—์„œ๋Š” ์ƒ์†์€ ์œ„ํ—˜ํ•˜๋‹ค.

์ƒ์†์˜ ์œ„ํ—˜์„ฑ

์ƒ์†์„ ํ•˜๊ฒŒ ๋˜๋ฉด ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์— ๋”ฐ๋ผ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ตญ ์บก์Аํ™”๋ฅผ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋œ๋‹ค. ์ƒ์œ„ ํด๋ž˜์Šค ์„ค๊ณ„ ์‹œ ํ™•์žฅ์„ ์ถฉ๋ถ„ํžˆ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ณ  ๋ฌธ์„œํ™”๋ฅผ ์ž˜ ํ•ด๋‘์ง€ ์•Š์œผ๋ฉด ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ณ€๊ฒฝ์— ์ทจ์•ฝํ•ด์ง€๊ฒŒ ๋œ๋‹ค.

๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ

์•„๋ž˜๋Š” HashSet์„ ์ƒ์†ํ•˜์—ฌ add / addAll์„ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์˜€์ง€๋งŒ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ์˜ˆ์‹œ์ด๋‹ค.

class InstrumentedHashSet<E> extends HashSet<E> {

    private int addCount = 0; // ์ถ”๊ฐ€๋œ ์›์†Œ์˜ ์ˆ˜

    public InstrumentedHashSet() {
    }

    public InstrumentedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
    }

    @Override
    public boolean add(E e) {
        addCount++; // 4. ๊ฐ ์›์†Œ๊ฐ€ ์ถ”๊ฐ€๋  ๋•Œ๋งˆ๋‹ค addCount ์ฆ๊ฐ€
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size(); // 2. addCount ์ฆ๊ฐ€
        return super.addAll(c); // 3. ์ƒ์œ„ ํด๋ž˜์Šค์˜ addAll ํ˜ธ์ถœ, addAll์€ ๋‚ด๋ถ€์ ์œผ๋กœ add๋ฅผ ํ˜ธ์ถœ
    }

    public int getAddCount() {
        return addCount;
    }
}

class Main {

    public static void main(String[] args) {
        InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
        s.addAll(List.of("ํ‹ฑ", "ํƒํƒ", "ํŽ‘")); // 1. addAll ํ˜ธ์ถœ
        System.out.println(s.getAddCount()); // 5. ๊ธฐ๋Œ€ํ•˜๋Š” 3์ด ์•„๋‹Œ 6์ด ์ถœ๋ ฅ๋จ
    }
}

์œ„์˜ ์ฃผ์„์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด addAll ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ addCount๊ฐ€ 3์ด ์ฆ๊ฐ€ํ•  ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” 6์ด ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋œ๋‹ค. HashSet์˜ addAll ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ add ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์ง€๋งŒ, ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ด๋ฅผ ์ธ์ง€ํ•˜๊ธฐ ์‰ฝ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค. ์ผ์‹œ์ ์œผ๋กœ addAll ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜์—ฌ ์ง์ ‘ ์ปฌ๋ ‰์…˜์„ ์ˆœํšŒํ•˜๋ฉฐ add ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์ˆ˜์ •ํ•˜๋ฉด ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐ๋˜์ง€๋งŒ, ๋‹ค๋ฅธ ์˜ค๋ฅ˜๋ฅผ ๋‚ด๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฐ๋‹ค.

์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€

์œ„์˜ ๋ฌธ์ œ๋Š” ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ด์ง€๋งŒ, ์ƒ์œ„ ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‹ค์Œ ๋ฒ„์ „์—์„œ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ ๋ฉ”์„œ๋“œ์™€ ๋™์ผํ•œ ์ด๋ฆ„์„ ๊ฐ€์ง„๋‹ค๋ฉด, ํ™•์žฅํ•œ ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ปดํŒŒ์ผ์กฐ์ฐจ ๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ํ•˜๊ฒŒ ๋˜์–ด ์ž˜๋ชป๋œ ๋™์ž‘์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

๋ฌธ์ œ๋ฅผ ํšŒํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•

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

  1. ํ™•์žฅํ•˜๋Š” ๋Œ€์‹  ์ƒˆ๋กœ์šด ํด๋ž˜์Šค ์ƒ์„ฑ

  2. private ํ•„๋“œ๋กœ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ•„๋“œ ์ถ”๊ฐ€(= composition)

  3. ์ƒˆ๋กœ์šด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์—์„œ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋Œ€์‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜(= forwarding)

    • ๋ž˜ํผ ํด๋ž˜์Šค(wrapper class): ๊ธฐ์กด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•„๋“œ๋กœ ๊ฐ–๊ณ  ์žˆ๋Š” ์ƒˆ ํด๋ž˜์Šค

    • ์ „๋‹ฌ ๋ฉ”์„œ๋“œ(forwarding method): ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋Š” ์ƒˆ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ

์œ„ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ๋ฐ”ํƒ•์œผ๋กœ ์ „๋‹ฌ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ƒˆ๋กœ์šด InstrumentedHashSet ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

์œ„ ์ฝ”๋“œ๋Š” Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•ด์„œ ์ „๋‹ฌ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋‹ค๋ฅธ Set ๊ตฌํ˜„์ฒด์—๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜์—ฌ ๋งค์šฐ ์œ ์—ฐํ•˜๊ฒŒ ์„ค๊ณ„๋œ ์˜ˆ์‹œ์ด๋‹ค. ์ƒ์† ๋ฐฉ์‹์€ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ๊ฐ๊ฐ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜์ง€๋งŒ, ์ปดํฌ์ง€์…˜ ๋ฐฉ์‹์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„์ฒด์— ์ƒ๊ด€์—†์ด ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒ์†์„ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ์ƒํ™ฉ

์•„๋ž˜ ๋‘ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•ด๋„ ์•ˆ์ „ํ•˜์ง€๋งŒ, ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ์—๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

  • ๋‘ ํด๋ž˜์Šค์˜ ๊ด€๊ณ„๊ฐ€ is-a ๊ด€๊ณ„์ธ ๊ฒฝ์šฐ (ํ•˜์œ„ ํด๋ž˜์Šค is a ์ƒ์œ„ ํด๋ž˜์Šค)

    • B๋Š” A๋‹ค ๋ผ๋Š” ๋ฌธ์žฅ์ด ์„ฑ๋ฆฝํ•ด์•ผ๋งŒ ํ•œ๋‹ค.

  • ์ƒ์†ํ•˜๋ ค๋Š” ์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ์ฒ˜์Œ์— ๋ช…์‹œ ๋œ ์กฐ๊ฑด(๋™์ผ ํŒจํ‚ค์ง€, ๋ฌธ์„œํ™”, ํ™•์žฅ์„ ๊ณ ๋ คํ•œ ์„ค๊ณ„)์„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ

์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ Stack/Vector, Properties/Hashtable ๋“ฑ์€ ์ƒ์†์„ ์‚ฌ์šฉํ•˜์˜€์ง€๋งŒ, is-a ๊ด€๊ณ„๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž˜๋ชป๋œ ์„ค๊ณ„๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Last updated