Design Pattern

[๋””์ž์ธ ํŒจํ„ด] ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด

devJK93 2025. 3. 24.

๐Ÿ“ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด?

ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์€ ๊ฐ์ฒด์ง€ํ–ฅ ๋””์ž์ธ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜๋‹ค.

๊ณตํ†ต๋œ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„ ์ฝ”๋“œ๋ฅผ ๋ถ€๋ชจ ํด๋ž˜์Šค์—์„œ ์ •์˜ํ•˜๊ณ , ์„ธ๋ถ€ ๊ตฌํ˜„์€ ์ž์‹ ํด๋ž˜์Šค์—์„œ ๋”ฐ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹.
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋™์ผํ•œ ๊ตฌ์กฐ์˜ ๊ป๋ฐ๊ธฐ๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ์“ฐ์ง€ ์•Š์•„๋„ ๋ผ์„œ ์ฝ”๋“œ๊ฐ€ ๊น”๋”ํ•ด์ง„๋‹ค.

[๋””์ž์ธ ํŒจํ„ด] ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด
๊ณตํ†ต ๋ถ€๋ถ„์ธ templateMethod(), ์ถ”์ƒ๋ถ€๋ถ„์ธ primitiveOperation1() primitiveOperation2()๋Š” ์ž์‹ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„

 

๐Ÿ“˜ ์˜ˆ์‹œ ์ฝ”๋“œ๋กœ ์ดํ•ดํ•ด๋ณด์ž

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒŒ์ž„ ์บ๋ฆญํ„ฐ๊ฐ€ ๊ณต๊ฒฉํ•˜๋Š” ๊ณผ์ •์„ ์ƒ๊ฐํ•ด๋ณด์ž.
๋ชจ๋“  ์บ๋ฆญํ„ฐ๋Š” "์ค€๋น„ -> ๊ณต๊ฒฉ -> ๋งˆ๋ฌด๋ฆฌ"๋ผ๋Š” ๊ณตํ†ต ํ๋ฆ„์„ ๊ฐ€์ง€๋Š”๋ฐ, ๊ตฌ์ฒด์ ์ธ ๊ณต๊ฒฉ ๋ฐฉ์‹์€ ์บ๋ฆญํ„ฐ๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค.
์ด๊ฑธ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด:

// ๋ถ€๋ชจ ํด๋ž˜์Šค
abstract class Character {
    // ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ: ๊ณตํ†ต ํ๋ฆ„ ์ •์˜
    public void attack() {
        System.out.println("์บ๋ฆญํ„ฐ๊ฐ€ ๊ณต๊ฒฉ์„ ์ค€๋น„ํ•œ๋‹ค.");
        System.out.println("์žฅ๋น„๋ฅผ ์ ๊ฒ€ํ•œ๋‹ค.");
        System.out.println("์ ์„ ์กฐ์ค€ํ•œ๋‹ค."); // context ๋ถ€๋ถ„์ด ๊ฝค ๊ธธ๋‹ค๊ณ  ๊ฐ€์ •
        call(); // ์ž์‹ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•  ๋ถ€๋ถ„
        System.out.println("๊ณต๊ฒฉ ํ›„ ํ”ผ๋กœ๋ฅผ ๋Š๋‚€๋‹ค.");
        System.out.println("์žฅ๋น„๋ฅผ ์ •๋ฆฌํ•œ๋‹ค.");
    }

    // ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๊ตฌํ˜„ํ•  ์ถ”์ƒ ๋ฉ”์„œ๋“œ
    abstract void call();
}

// ์ž์‹ ํด๋ž˜์Šค 1
class Warrior extends Character {
    @Override
    void call() {
        System.out.println("์ „์‚ฌ๊ฐ€ ์นผ์„ ํœ˜๋‘๋ฅธ๋‹ค.");
    }
}

// ์ž์‹ ํด๋ž˜์Šค 2
class Mage extends Character {
    @Override
    void call() {
        System.out.println("๋งˆ๋ฒ•์‚ฌ๊ฐ€ ๋ถˆ๋ฉ์ด๋ฅผ ์œ๋‹ค.");
    }
}

public class Main {
    public static void main(String[] args) {
        Character warrior = new Warrior();
        Character mage = new Mage();
        
        warrior.attack();
        System.out.println("---");
        mage.attack();
    }
}
    

์—ฌ๊ธฐ์„œ attack() ๋ฉ”์„œ๋“œ๊ฐ€ ํ…œํ”Œ๋ฆฟ.

๊ณตํ†ต ๋ถ€๋ถ„์ธ "์ค€๋น„ -> ๋งˆ๋ฌด๋ฆฌ"๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , call()์€ ์ž์‹ ํด๋ž˜์Šค์—์„œ ๊ฐ์ž ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•œ๋‹ค.

์ฝ”๋“œ ์ค‘๋ณต์ด ์ค„์–ด๋“œ๋Š” ๊ฒŒ ๋Š๊ปด์ง„๋‹ค.

โš ๏ธ ๋ฌธ์ œ์ : ํด๋ž˜์Šค๋ฅผ ๊ณ„์† ์ฐ์–ด๋‚ด์•ผ ํ•œ๋‹ค.

๊ทผ๋ฐ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์€ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๊ณ„์† ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ถˆํŽธํ•จ์ด ์žˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ์บ๋ฆญํ„ฐ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•ด์•ผ ํ•˜๋‹ˆ๊นŒ ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฑธ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค.

โ˜๏ธ ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ

์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋Š” ํด๋ž˜์Šค๋ฅผ ๋ณ„๋„๋กœ ์ •์˜ํ•˜์ง€ ์•Š๊ณ , ๋ฐ”๋กœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ๊ตฌํ˜„์„ ๋„ฃ๋Š” ๋ฐฉ์‹.
์œ„ ์ฝ”๋“œ๋ฅผ ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋กœ ๋ฐ”๊พธ๋ฉด:

public class Main {
    public static void main(String[] args) {
        // ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค 1: ์ „์‚ฌ
        Character warrior = new Character() {
            @Override
            void call() {
                System.out.println("์ „์‚ฌ๊ฐ€ ์นผ์„ ํœ˜๋‘๋ฅธ๋‹ค.");
            }
        };

        // ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค 2: ๋งˆ๋ฒ•์‚ฌ
        Character mage = new Character() {
            @Override
            void call() {
                System.out.println("๋งˆ๋ฒ•์‚ฌ๊ฐ€ ๋ถˆ๋ฉ์ด๋ฅผ ์œ๋‹ค.");
            }
        };

        warrior.attack();
        System.out.println("---");
        mage.attack();

        // ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค์˜ ํด๋ž˜์Šค ์ด๋ฆ„ ํ™•์ธ
        System.out.println("Warrior ํด๋ž˜์Šค ์ด๋ฆ„: " + warrior.getClass());
        System.out.println("Mage ํด๋ž˜์Šค ์ด๋ฆ„: " + mage.getClass());
    }
}
    

 

์‹คํ–‰ํ•˜๋ฉด Main$1, Main$2 ๊ฐ™์€ ์‹์œผ๋กœ ์ถœ๋ ฅ๋œ๋‹ค.
์ด๊ฑด ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๊ฐ€ ์ž๊ธฐ๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ํด๋ž˜์Šค(Main) ์ด๋ฆ„์— ๋ฒˆํ˜ธ๋ฅผ ๋ถ™์—ฌ์„œ ๋งŒ๋“ค์–ด์ง„๋‹ค๋Š” ๋œป์ด๋‹ค.

๋ณ„๋„์˜ ํด๋ž˜์Šค ํŒŒ์ผ์„ ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ๋ผ์„œ ํŽธ๋ฆฌํ•˜๋‹ค.

โ˜๏ธ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค ๋ฌธ๋ฒ•

์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋Š” ์ด๋ ‡๊ฒŒ ์“ด๋‹ค:

new ๋ถ€๋ชจํด๋ž˜์Šค() {
    @Override
    void ๋ฉ”์„œ๋“œ() {
        // ๊ตฌํ˜„ ๋‚ด์šฉ
    }
};
    

์ธํ„ฐํŽ˜์ด์Šค๋‚˜ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ฃผ๋กœ ์“ฐ์ด๊ณ , ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉํ•  ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ ์œ ์šฉํ•˜๋‹ค.

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

  • ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ถ€๋ชจ ํด๋ž˜์Šค์— ๊ฐ•ํ•˜๊ฒŒ ์˜์กดํ•œ๋‹ค. ๋ถ€๋ชจ์˜ ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊พธ๋ฉด ์ž์‹ ํด๋ž˜์Šค๋„ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค.
  • ๋ณ„๋„์˜ ํด๋ž˜์Šค๋‚˜ ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ์œ„์—์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ํด๋ž˜์Šค๋ฅผ ๊ณ„์† ์ •์˜ํ•˜๊ฑฐ๋‚˜ ์ต๋ช… ๋‚ด๋ถ€ ํด๋ž˜์Šค๋กœ ๋Œ€์ฒดํ•ด์•ผ ํ•œ๋‹ค.

๋งˆ๋ฌด๋ฆฌ

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