๋””์ž์ธ ํŒจํ„ด/GOF

๐Ÿ’  ์ถ”์ƒ ํŒฉํ† ๋ฆฌ(Abstract Factory) ํŒจํ„ด - ์™„๋ฒฝ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ

์ธํŒŒ_ 2023. 1. 11. 08:59

Abstract-Factory-pattern
Abstract-Factory-pattern

Abstract Factory Pattern

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

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


์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด ๊ตฌ์กฐ

Abstract-Factory-pattern

  • AbstractFactory : ์ตœ์ƒ์œ„ ๊ณต์žฅ ํด๋ž˜์Šค. ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ œํ’ˆ๋“ค์„ ์ƒ์„ฑํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ถ”์ƒํ™” ํ•œ๋‹ค.
  • ConcreteFactory : ์„œ๋ธŒ ๊ณต์žฅ ํด๋ž˜์Šค๋“ค์€ ํƒ€์ž…์— ๋งž๋Š” ์ œํ’ˆ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ฉ”์†Œ๋“œ๋“ค์„ ์žฌ์ •์˜ํ•œ๋‹ค.
  • AbstractProduct : ๊ฐ ํƒ€์ž…์˜ ์ œํ’ˆ๋“ค์„ ์ถ”์ƒํ™”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • ConcreteProduct (ProductA ~ ProductB) : ๊ฐ ํƒ€์ž…์˜ ์ œํ’ˆ ๊ตฌํ˜„์ฒด๋“ค. ์ด๋“ค์€ ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ๋‹ค. 
  • Client : Client๋Š” ์ถ”์ƒํ™”๋œ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ์„ ์ด์šฉํ•˜์—ฌ ์ œํ’ˆ์„ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—, ๊ตฌ์ฒด์ ์ธ ์ œํ’ˆ, ๊ณต์žฅ์— ๋Œ€ํ•ด์„œ๋Š” ๋ชจ๋ฅธ๋‹ค.

 

Abstract Factory vs Factory Method

๋‘˜๋‹ค ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ๊ฐ์ถ”๊ณ  ๊ฐ์ฒด ์ƒ์„ฑ์— ๊ด€์—ฌํ•˜๋Š” ํŒจํ„ด ์ž„์—๋Š” ๋™์ผํ•˜๋‹ค. ๋˜ํ•œ ๊ณต์žฅ ํด๋ž˜์Šค๊ฐ€ ์ œํ’ˆ ํด๋ž˜์Šค๋ฅผ ๊ฐ๊ฐ ๋‚˜๋‰˜์–ด ๋Š์Šจํ•œ ๊ฒฐํ•ฉ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ์Šต ์—ญ์‹œ ๋‘˜์ด ์œ ์‚ฌํ•˜๋‹ค.

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

๋‹จ, ์ด ๋‘˜์„ ์œ ์‚ฌ์ ๊ณผ ์ฐจ์ด์ ์„ ์กฐํ•ฉํ•ด์„œ ๋ณตํ•ฉ ํŒจํ„ด์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด
๊ณตํ†ต์  ๊ฐ์ฒด ์ƒ์„ฑ ๊ณผ์ •์„ ์ถ”์ƒํ™”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณต
๊ฐ์ฒด ์ƒ์„ฑ์„ ์บก์Šํ™”ํ•จ์œผ๋กœ์จ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ๊ฐ์ถ”๊ณ  ๋Š์Šจํ•œ ๊ฒฐํ•ฉ ๊ตฌ์กฐ๋ฅผ ํ‘œ๋ฐฉ
์ฐจ์ด์  ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ์ •์„ ํ•˜์œ„ ๋˜๋Š” ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์ด ๋ชฉ์  ๊ด€๋ จ ์žˆ๋Š” ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ๋ชฉ์ 
ํ•œ Factory๋‹น ํ•œ ์ข…๋ฅ˜์˜ ๊ฐ์ฒด ์ƒ์„ฑ ์ง€์› ํ•œ Factory์—์„œ ์„œ๋กœ ์—ฐ๊ด€๋œ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ๊ฐ์ฒด ์ƒ์„ฑ์„ ์ง€์›. (์ œํ’ˆ๊ตฐ ์ƒ์„ฑ ์ง€์›)
๋ฉ”์†Œ๋“œ ๋ ˆ๋ฒจ์—์„œ ํฌ์ปค์Šค๋ฅผ ๋งž์ถค์œผ๋กœ์จ, ํด๋ผ์ด์–ธํŠธ์˜ ConcreteProduct ์ธ์Šคํ„ด์Šค์˜ ์ƒ์„ฑ ๋ฐ ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ์˜์กด์„ ๊ฐ์†Œ ํด๋ž˜์Šค(Factory) ๋ ˆ๋ฒจ์—์„œ ํฌ์ปค์Šค๋ฅผ ๋งž์ถค์œผ๋กœ์จ, ํด๋ผ์ด์–ธํŠธ์˜ ConcreteProduct ์ธ์Šคํ„ด์Šค ๊ตฐ์˜ ์ƒ์„ฑ ๋ฐ ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ์˜์กด์„ ๊ฐ์†Œ

์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด ํ๋ฆ„

ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ๊ตฌ์„ฑ์š”์†Œ์™€ ํ™”์‚ดํ‘œ๊ฐ€ ์–ผํ‚ค๊ณ  ์„ฅํ˜€ ๋ณต์žกํ•˜๊ฒŒ ๋ณด์ผํ…Œ์ง€๋งŒ, ์‹ค์ƒ ํŒŒ๊ณ ๋ณด๋ฉด ๋ณ„๊ฑฐ ์•„๋‹Œ ๊ตฌ์กฐ์ด๋‹ˆ ๊ฒ ๋จน์„ ํ•„์š”๊ฐ€ ์—†๋‹ค.

 

ํด๋ž˜์Šค ๊ตฌ์„ฑ

Abstract-Factory-pattern

 

์ œํ’ˆ(Product) ํด๋ž˜์Šค

// Product A ์ œํ’ˆ๊ตฐ
interface AbstractProductA {
}

// Product A - 1
class ConcreteProductA1 implements AbstractProductA {
}

// Product A - 2
class ConcreteProductA2 implements AbstractProductA {
}
// Product B ์ œํ’ˆ๊ตฐ
interface AbstractProductB {
}

// Product B - 1
class ConcreteProductB1 implements AbstractProductB {
}

// Product B - 2
class ConcreteProductB2 implements AbstractProductB {
}

 

๊ณต์žฅ(Factory) ํด๋ž˜์Šค

interface AbstractFactory {
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}

// Product A1์™€ B1 ์ œํ’ˆ๊ตฐ์„ ์ƒ์‚ฐํ•˜๋Š” ๊ณต์žฅ๊ตฐ 1 
class ConcreteFactory1 implements AbstractFactory {
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }
}

// Product A2์™€ B2 ์ œํ’ˆ๊ตฐ์„ ์ƒ์‚ฐํ•˜๋Š” ๊ณต์žฅ๊ตฐ 2
class ConcreteFactory2 implements AbstractFactory {
    public AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }
    public AbstractProductB createProductB() {
        return new ConcreteProductB2();
    }
}

 

ํด๋ž˜์Šค ํ๋ฆ„

Abstract-Factory-pattern

class Client {
    public static void main(String[] args) {
    	AbstractFactory factory = null;
        
        // 1. ๊ณต์žฅ๊ตฐ 1์„ ๊ฐ€๋™์‹œํ‚จ๋‹ค.
        factory = new ConcreteFactory1();

        // 2. ๊ณต์žฅ๊ตฐ 1์„ ํ†ตํ•ด ์ œํ’ˆ๊ตฐ A1๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ํ•œ๋‹ค (ํด๋ผ์ด์–ธํŠธ๋Š” ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์€ ๋ชจ๋ฅด๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•œ๋‹ค)
        AbstractProductA product_A1 = factory.createProductA();
        System.out.println(product_A1.getClass().getName()); // ConcreteProductA1

        // 3. ๊ณต์žฅ๊ตฐ 2๋ฅผ ๊ฐ€๋™์‹œํ‚จ๋‹ค.
        factory = new ConcreteFactory2();

        // 4. ๊ณต์žฅ๊ตฐ 2๋ฅผ ํ†ตํ•ด ์ œํ’ˆ๊ตฐ A2๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ํ•œ๋‹ค (ํด๋ผ์ด์–ธํŠธ๋Š” ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์€ ๋ชจ๋ฅด๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•œ๋‹ค)
        AbstractProductA product_A2 = factory.createProductA();
        System.out.println(product_A2.getClass().getName()); // ConcreteProductA2
    }
}

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋˜‘๊ฐ™์€ createProductA() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋งŒ ์–ด๋–ค ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด์ด๋ƒ์— ๋”ฐ๋ผ ๋ฐ˜ํ™˜๋˜๋Š” ์ œํ’ˆ๊ตฐ์ด ๋‹ค๋ฅด๊ฒŒ ๋œ๋‹ค.

Abstract-Factory-pattern


์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด ํŠน์ง•

 

ํŒจํ„ด ์‚ฌ์šฉ ์‹œ๊ธฐ

  • ๊ด€๋ จ ์ œํ’ˆ์˜ ๋‹ค์–‘ํ•œ ์ œํ’ˆ ๊ตฐ๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•ด์•ผ ํ• ๋•Œ, ํ•ด๋‹น ์ œํ’ˆ์˜ ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ
  • ์—ฌ๋Ÿฌ ์ œํ’ˆ๊ตฐ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด์„œ ์‹œ์Šคํ…œ์„ ์„ค์ •ํ•ด์•ผํ•˜๊ณ  ํ•œ ๋ฒˆ ๊ตฌ์„ฑํ•œ ์ œํ’ˆ์„ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜๋„ ์žˆ์„ ๋•Œ
  • ์ œํ’ˆ์— ๋Œ€ํ•œ ํด๋ž˜์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜๊ณ , ๊ทธ๋“ค์˜ ๊ตฌํ˜„์ด ์•„๋‹Œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋…ธ์ถœ์‹œํ‚ค๊ณ  ์‹ถ์„ ๋•Œ

 

ํŒจํ„ด ์žฅ์ 

 

ํŒจํ„ด ๋‹จ์ 

  • ๊ฐ ๊ตฌํ˜„์ฒด๋งˆ๋‹ค ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด๋“ค์„ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด๊ฐ€ ๋Š˜์–ด๋‚ ๋•Œ ๋งˆ๋‹ค ํด๋ž˜์Šค๊ฐ€ ์ฆ๊ฐ€ํ•˜์—ฌ ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€ํ•œ๋‹ค. (ํŒฉํ† ๋ฆฌ ํŒจํ„ด์˜ ๊ณตํ†ต์ ์ธ ๋ฌธ์ œ์ )
  • ๊ธฐ์กด ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์˜ ์„ธ๋ถ€์‚ฌํ•ญ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ชจ๋“  ํŒฉํ† ๋ฆฌ์— ๋Œ€ํ•œ ์ˆ˜์ •์ด ํ•„์š”ํ•ด์ง„๋‹ค. ์ด๋Š” ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์™€ ๋ชจ๋“  ์„œ๋ธŒํด๋ž˜์Šค์˜ ์ˆ˜์ •์„ ๊ฐ€์ ธ์˜จ๋‹ค. 
  • ์ƒˆ๋กœ์šด ์ข…๋ฅ˜์˜ ์ œํ’ˆ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ต๋‹ค. ์ƒˆ๋กœ์šด ์ œํ’ˆ์ด ์ถ”๊ฐ€๋˜๋ฉด ํŒฉํ† ๋ฆฌ ๊ตฌํ˜„ ๋กœ์ง ์ž์ฒด๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผํ•œ๋‹ค.

์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด๋Š” ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์™€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด ์ฐจ์ด์— ๋Œ€ํ•ด ํ–‡๊น”๋ ค ํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋‘˜์ด ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด๊ฐ€ ๋Œ€์‹  ์ œํ’ˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์ ์—์„œ ๊ตฌ์กฐ๊ฐ€ ๊ฑฐ์˜ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์–ด๋–ค ๋””์ž์ธ ํŒจํ„ด ์„œ์ ์—์„œ๋Š” ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์™€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜๋‚˜์˜ ํŒฉํ† ๋ฆฌ ํŒจํ„ด ์นดํ…Œ๊ณ ๋ฆฌ๋กœ์„œ ๋‹ค๋ฃจ๊ธฐ๋„ ํ•œ๋‹ค.

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

 

์ปดํ“จํ„ฐ ํ™”๋ฉด์— ์ปดํฌ๋„ŒํŠธ ์š”์†Œ๋“ค์„ ํ™”๋ฉด์— ๊ทธ๋ฆฌ๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ๋ฒ„ํŠผ(Button), CheckBox(์ฒดํฌ๋ฐ•์Šค), TextEdit(ํ…์ŠคํŠธ๋ฐ•์Šค) 3๊ฐ€์ง€ ์š”์†Œ๋ฅผ ํ™”๋ฉด์— ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•ด ๊ฐ๊ธฐ ๊ฐ์ฒด๋กœ ์ง€์ •ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ปดํ“จํ„ฐ OS์—๋Š” ์œˆ๋„์šฐ(Window)์™€ ๋งฅ(Mac) ์ข…๋ฅ˜๊ฐ€ ๋‚˜๋‰˜๋Š”๋ฐ ์–ด๋–ค OS๋ƒ์— ๋”ฐ๋ผ์„œ ๋ชจ์–‘์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ธฐ ์ƒ์„ฑํ•˜์—ฌ ๊ตฌํ˜„ํ•˜์—ฌ์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

์ •๋ฆฌํ•˜๋ฉด ์ด 3๊ฐ€์ง€ ๊ฐ์ฒด๋“ค์€ ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ(Component) ๊ตฐ์œผ๋กœ ๋ฌถ์„์ˆ˜ ์žˆ์œผ๋ฉฐ ๋˜ํ•œ OS๋ณ„ ๊ตฐ์œผ๋กœ ๋‚˜๋‰˜๊ฒŒ ๋œ๋‹ค.

Abstract-Factory-pattern

์œ„์˜ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Abstract-Factory-pattern

interface Component {
    void render(); // ์š”์†Œ ๊ทธ๋ฆฌ๊ธฐ
}

/* ---------------------------------------------------------- */

abstract class Button implements Component {
}

class WindowButton extends Button {
    @Override
    public void render() {
        System.out.println("์œˆ๋„์šฐ ๋ฒ„ํŠผ ์ƒ์„ฑ ์™„๋ฃŒ");
    }
}

class MacButton extends Button {
    @Override
    public void render() {
        System.out.println("๋งฅ ๋ฒ„ํŠผ ์ƒ์„ฑ ์™„๋ฃŒ");
    }
}

/* ---------------------------------------------------------- */

abstract class CheckBox implements Component {
}

class WindowCheckBox extends CheckBox {
    @Override
    public void render() {
        System.out.println("์œˆ๋„์šฐ ์ฒดํฌ๋ฐ•์Šค ์ƒ์„ฑ ์™„๋ฃŒ");
    }
}

class MacCheckBox extends CheckBox {
    @Override
    public void render() {
        System.out.println("๋งฅ ์ฒดํฌ๋ฐ•์Šค ์ƒ์„ฑ ์™„๋ฃŒ");
    }
}

/* ---------------------------------------------------------- */

abstract class TextEdit implements Component {
}

class WindowTextEdit extends TextEdit {
    @Override
    public void render() {
        System.out.println("์œˆ๋„์šฐ ํ…์ŠคํŠธ๋ฐ•์Šค ์ƒ์„ฑ ์™„๋ฃŒ");
    }
}

class MacTextEdit extends TextEdit {
    @Override
    public void render() {
        System.out.println("๋งฅ ํ…์ŠคํŠธ๋ฐ•์Šค ์ƒ์„ฑ ์™„๋ฃŒ");
    }
}

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„

์œ„์˜ ๊ตฌ์„ฑ์„ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด์ž. ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์˜ ๊ณต์žฅ ๊ฐ์ฒด๋Š” ํ•œ๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ์ปดํฌ๋„ŒํŠธ๋งŒ ์ƒ์„ฑํ•˜๋Š” ๊ตฌ์กฐ์ด๋‹ค. ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ์ดˆ์ ์€ ์ถ”์ƒํ™”๋œ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ ์„œ๋ธŒ ๊ณต์žฅ ํด๋ž˜์Šค๊ฐ€ ์žฌ์ •์˜ํ•˜์—ฌ ๊ฑธ๋งž๋Š” ์ œํ’ˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ฒ„ํŠผ์„ ์ƒ์„ฑํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ์–ด๋Š OS ์‹คํ–‰ํ™˜๊ฒฝ์ธ์ง€๋Š” ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ๋ถ„๊ธฐ๋ฌธ์„ ํ†ตํ•ด ๊ตฌ๋ถ„ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

Factory-pattern

interface ComponentFactoryMethod {
    Component createOperation(String type); // ํ…œํ”Œ๋ฆฟ
    Component createComponent(String type); // ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ
}

class ButtonFactory implements ComponentFactoryMethod {

    public Button createOperation(String type) {
        Button button = createComponent(type);
        button.์ถ”๊ฐ€์„ค์ •();
        return button;
    }

    public Button createComponent(String type) {

        Button button = null;

        switch (type.toLowerCase()) {
            case "window":
                button = new WindowButton();
                break;

            case "mac":
                button = new MacButton();
                break;
        }

        return button;
    }
}

class CheckBoxFactory implements ComponentFactoryMethod {
    public CheckBox createOperation(String type) {
        CheckBox checkbox = createComponent(type);
        checkbox.์ถ”๊ฐ€์„ค์ •();
        return checkbox;
    }

    public CheckBox createComponent(String type) {

        CheckBox checkbox = null;

        switch (type.toLowerCase()) {
            case "window":
                checkbox = new WindowCheckBox();
                break;

            case "mac":
                checkbox = new MacCheckBox();
                break;
        }

        return checkbox;
    }
}

class TextEditFactory implements ComponentFactoryMethod {
    public TextEdit createOperation(String type) {
        TextEdit txtedit = createComponent(type);
        txtedit.์ถ”๊ฐ€์„ค์ •();
        return txtedit;
    }

    public TextEdit createComponent(String type) {

        TextEdit txtedit = null;

        switch (type.toLowerCase()) {
            case "window":
                txtedit = new WindowTextEdit();
                break;

            case "mac":
                txtedit = new MacTextEdit();
                break;
        }

        return txtedit;
    }
}
public static void main(String[] args) {
    ComponentFactoryMethod factory = null;
    Button btn = null;
    CheckBox chkBox = null;

    // ์œˆ๋„์šฐ ๋ฒ„ํŠผ ์ƒ์„ฑ
    factory = new ButtonFactory();
    btn = (Button) factory.createOperation("Window");
    btn.render();

    // ๋งฅ ๋ฒ„ํŠผ ์ƒ์„ฑ
    btn = (Button) factory.createOperation("Mac");
    btn.render();

    // ์œˆ๋„์šฐ ์ฒดํฌ ๋ฐ•์Šค ์ƒ์„ฑ
    factory = new CheckBoxFactory();
    chkBox = (CheckBox) factory.createOperation("Window");
    chkBox.render();

    // ๋งฅ ์ฒดํฌ ๋ฐ•์Šค ์ƒ์„ฑ
    chkBox = (CheckBox) factory.createOperation("Mac");
    chkBox.render();
}

Factory-pattern

 

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ๋ฌธ์ œ์ 

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋กœ ๊ตฌํ˜„ํ•ด๋ณธ ์ฝ”๋“œ๋Š” ์‹คํ–‰ ์ž์ฒด๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์ด์ง€๋งŒ, ๋งŒ์ผ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด OS ์ข…๋ฅ˜์— Linux๋ฅผ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ๊ทธ๋Ÿฌ๋ฉด ๊ฐ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ์žˆ๋Š” ๋ถ„๊ธฐ๋ฌธ ๋กœ์ง์„ ์ผ์ผํžˆ ์ˆ˜์ •ํ•˜์—ฌ์•ผ ํ•˜๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด OCP ์›์น™์— ์œ„๋ฐฐ๋˜๋Š” ๊ผด์ด ๋œ๋‹ค.

Factory-pattern


์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„

๊ทธ๋Ÿผ ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์–ด๋–จ๊นŒ?

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

Abstract-Factory-pattern

interface ComponentAbstractFactory {
    Button createButton();
    CheckBox createCheckBox();
    TextEdit createTextEdit();
}

class WindowFactory implements ComponentAbstractFactory {

    @Override
    public Button createButton() {
        return new WindowButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new WindowCheckBox();
    }

    @Override
    public TextEdit createTextEdit() {
        return new WindowTextEdit();
    }
}

class MacFactory implements ComponentAbstractFactory {

    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new MacCheckBox();
    }

    @Override
    public TextEdit createTextEdit() {
        return new MacTextEdit();
    }
}
public static void main(String[] args) {
    ComponentAbstractFactory factory = null;

    // ์œˆ๋„์šฐ ๋ฒ„ํŠผ ์ƒ์„ฑ
    factory = new WindowFactory();
    Button WindowBtn = createBtn(factory);
    WindowBtn.render();

    // ๋งฅ ๋ฒ„ํŠผ ์ƒ์„ฑ
    factory = new MacFactory();
    Button MacBtn = createBtn(factory);
    MacBtn.render();
}

// ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„ ์ฝ”๋“œ๋Š” ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ๋ฉ”์„œ๋“œ๋กœ ๋ฌถ์Œ ๋ถ„๋ฆฌ
public static Button createBtn(ComponentAbstractFactory fac) {
    return fac.createButton();
}

Abstract-Factory-pattern
Abstract-Factory-pattern

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

ํ•˜์ง€๋งŒ ์ฐฉ๊ฐํ•˜์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ์ด ์ถ”์ƒ ํŒฉํ† ๋ฆฌ๊ฐ€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ณด๋‹ค ๋ฌด์กฐ๊ฑด ์ข‹๋‹ค๋Š” ๋ง์ด ์•„๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ ์ฒ˜๋Ÿผ ์–ด๋– ํ•œ ์ œํ’ˆ๋“ค์— ๋Œ€ํ•œ '๊ตฐ'์„ ๋ฌถ์–ด ์ƒ์„ฑํ•ด์•ผ ํ• ๋•Œ ์ถ”์ƒ ํŒฉํ† ๋ฆฌ๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์œ ์ง€๋ณด์ˆ˜์™€ ํ™•์žฅ์— ์žˆ์–ด ๋” ์œ ๋ฆฌํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

์ถ”์ƒ ํŒฉํ† ๋ฆฌ์˜ ์œ ์—ฐํ•œ ํ™•์žฅ

์˜ˆ๋ฅผ๋“ค์–ด Linux OS ํ™˜๊ฒฝ์ด ์ถ”๊ฐ€๋œ๋‹ค ํ•˜๋”๋ผ๋„, ๊ธฐ์กด์˜ ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด ๋ฆฌ๋ˆ…์Šค ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„์ฒด ํด๋ž˜์Šค์™€ ๋ฆฌ๋ˆ…์Šค ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋งŒ ์ ์ ˆํ•˜๊ฒŒ ์ถ”๊ฐ€๋งŒ ํ•ด์ฃผ๋ฉด ํ™•์žฅ์ด ์™„๋ฃŒ๋˜๊ฒŒ ๋œ๋‹ค.

๊ธฐ์กด ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ์„ค๊ณ„ ํ–ˆ์„๋•Œ๋Š” ๋ฉ”์„œ๋“œ์˜ ๋ถ„๊ธฐ๋ฌธ์„ ์ผ์ผํžˆ ๋œฏ์–ด ๊ณ ์น˜๋Š” ๊ฒƒ์— ๋น„ํ•˜๋ฉด ํ™•์‹คํžˆ OCP ์›์น™์˜ ์ˆ˜์ •์—๋Š” ๋‹ซํ˜€์žˆ๊ณ  ํ™•์žฅ์—๋Š” ์—ด๋ ค์žˆ๋‹ค๋Š” ๋ง์ด ๋ฌด์Šจ ์˜๋ฏธ์ธ์ง€ ์ฒด๊ฐ์ด ์˜จ๋‹ค.

Abstract-Factory-pattern

 

์ถ”์ƒ ํŒฉํ† ๋ฆฌ์˜ ๋ฌธ์ œ์ 

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

Abstract-Factory-pattern

 

์ถ”์ƒ ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด ์‹ฑ๊ธ€ํ†คํ™”

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

Abstract-Factory-pattern

๋ฌผ๋ก  ์œ„์™€ ๊ฐ™์ด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์šฉ์œผ๋กœ ์ผํšŒ์šฉ์œผ๋กœ ์“ฐ์ธ ์ธ์Šคํ„ด์Šค๋Š” JVM์˜ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜(GC) ์— ์˜ํ•ด ์ž๋™์œผ๋กœ ์ง€์›Œ์ง€์ง€๋งŒ, ์ด๋Ÿฐ ๊ฐ€๋น„์ง€ ๊ฐ’์ด ๋Š˜์–ด๋‚˜๊ฒŒ๋˜๋ฉด ๋‚˜์ค‘์— ๊ฐ์ฒด ์ œ๊ฑฐ ๊ณผ์ •์—์„œ Stop-the-world ๊ฐ€ ์ผ์–ด๋‚˜๊ฒŒ ๋œ๋‹ค. (ํ”„๋กœ๊ทธ๋žจ์ด ๋ ‰๊ฑธ๋ฆผ)

๋”ฐ๋ผ์„œ ๊ฐ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋“ค์„ ์‹ฑ๊ธ€ํ†ค(Singleton) ํ™” ์‹œ์ผœ ๋ฉ”๋ชจ๋ฆฌ ์ ์œผ๋กœ ์ตœ์ ํ™”๋ฅผ ์‹œํ‚จ๋‹ค.

class WindowFactory implements ComponentAbstractFactory {

    // ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒดํ™”
    private WindowFactory() {
    }
    private static class SingleInstanceHolder {
        private static final WindowFactory INSTANCE = new WindowFactory();
    }
    public static WindowFactory getInstance() {
        return SingleInstanceHolder.INSTANCE;
    }

    @Override
    public Button createButton() {
        return new WindowButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new WindowCheckBox();
    }

    @Override
    public TextEdit createTextEdit() {
        return new WindowTextEdit();
    }
}

class MacFactory implements ComponentAbstractFactory {

    // ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒดํ™”
    private MacFactory() {
    }
    private static class SingleInstanceHolder {
        private static final MacFactory INSTANCE = new MacFactory();
    }
    public static MacFactory getInstance() {
        return MacFactory.SingleInstanceHolder.INSTANCE;
    }

    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new MacCheckBox();
    }

    @Override
    public TextEdit createTextEdit() {
        return new MacTextEdit();
    }
}

Abstract-Factory-pattern-singleton
Abstract-Factory-pattern-singleton


์ถ”์ƒ ํŒฉํ† ๋ฆฌ + ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด ์กฐํ•ฉ

์‚ฌ๋žŒ๋“ค์ด ๋งŽ์ด๋“ค ์ฐฉ๊ฐํ•˜๋Š” ๋ถ€๋ถ„์ด ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์™€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” 2์ง€ ์„ ๋‹คํ˜•์œผ๋กœ ์•Œ๊ณ  ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด ๋‘˜์€ ์—„์—ฐํžˆ ๋ณ„๊ฐœ์˜ ์ฝ”๋“œ ํŒจํ„ด์ด๋‹ค.

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

 

์•„๋ž˜์˜ ์˜ˆ์ œ ์ฝ”๋“œ๋Š” OS ๊ตฐ ๋ณ„๋กœ ์ถ”์ƒ ํŒฉํ† ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•˜๋ฉฐ, ๊ฐ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด์„œ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ๊ตฌ์„ฑํ•œ ์˜ˆ์ œ์ด๋‹ค. ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ํ…œํ”Œ๋ฆฟ์€ ํ•œ๊บผ๋ฒˆ์— ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ƒ์„ฑํ•˜๊ณ  ์ถ”๊ฐ€ ์„ธํŒ…ํ•œ๋‹ค๋Š” ์ปจ์…‰์œผ๋กœ์จ ํ•˜๋‚˜์˜ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฌถ์–ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋งŒ์ผ ๋ฒ„ํŠผ ๋”ฐ๋กœ, ์ฒดํฌ๋ฐ•์Šค ๋”ฐ๋กœ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋ณ„๋„์˜ createButtonOperation() ์ด๋‚˜ createCheckBoxOperation() ๋ฉ”์„œ๋“œ๋กœ ๊ฐ๊ธฐ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

interface ComponentAbstractFactoryMethod {
	// ์„œ๋ธŒ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋“ค
    Button createButton(); 
    CheckBox createCheckBox();
    TextEdit createTextEdit();
	
    // ํŒฉํ† ๋ฆฌ ํ…œํ”Œ๋ฆฟ
    default List<Component> createOperation() {
        Button btn = createButton();
        CheckBox chkbox = createCheckBox();
        TextEdit txtEdt = createTextEdit();
        btn.์ถ”๊ฐ€์„ธํŒ…();
        chkbox.์ถ”๊ฐ€์„ธํŒ…();
        txtEdt.์ถ”๊ฐ€์„ธํŒ…();

        return new ArrayList<Component>(Arrays.asList(btn, chkbox, txtEdt));
    }
}

// ์ถ”์ƒ ํŒฉํ† ๋ฆฌ
class WindowFactoryMethod implements ComponentAbstractFactoryMethod {

    @Override
    public Button createButton() {
        return new WindowButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new WindowCheckBox();
    }

    @Override
    public TextEdit createTextEdit() {
        return new WindowTextEdit();
    }
}

// ์ถ”์ƒ ํŒฉํ† ๋ฆฌ
class MacFactoryMethod implements ComponentAbstractFactoryMethod {
	// ...
}
public static void main(String[] args) {
    ComponentAbstractFactoryMethod factory = null;

    // ์œˆ๋„์šฐ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ
    factory = new WindowFactoryMethod();
    List<Component> list = factory.createOperation();

    System.out.println(list);
    for(Component c: list) {
        c.render();
    }
}

Abstract-Factory-pattern


์‹ค๋ฌด์—์„œ ์ฐพ์•„๋ณด๋Š” ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด

 

Java

  • javax.xml.parsers.DocumentBuilderFactory ์˜ newInstance()
  • javax.xml.transform.TransformerFactory ์˜ newInstance()
  • javax.xml.xpath.XPathFactory ์˜ newInstance()

 

DocumentBuilderFactory ์˜ newInstance()

Java๋Š” xmlํ˜•์‹์˜ ๋ฌธ์„œ๋ฅผ ๊ฐ์ฒดํ™” ์‹œ์ผœ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋Š” DocumentBuilder ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ ์ด ๊ฐ์ฒด๋Š” ๋ฐ”๋กœ DocumentBuilderFactory๋กœ๋ถ€ํ„ฐ ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค. 

newInstance()๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ค๋Š” DocumentBuilderFactory ํƒ€์ž…์˜ ๊ฐ์ฒด๊ฐ€ ConcreteFactory์— ํ•ด๋‹นํ•˜๊ณ  ConcreteFactory๊ฐ€ ์ œ๊ณตํ•˜๋Š” DocumentBuilder๊ฐ€ ์ถ”์ƒํ™”๋œ ๊ฐ์ฒด(์ œํ’ˆ)์— ํ•ด๋‹นํ•˜๊ฒŒ ๋œ๋‹ค.

public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
    // 1. ๊ณต์žฅ ๊ฐ์ฒด ์ƒ์„ฑ
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    
    // 2. ๊ณต์žฅ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์ถ”์ƒํ™”๋œ ์ œํ’ˆ ๊ฐ์ฒด ์ƒ์„ฑ
    DocumentBuilder builder = factory.newDocumentBuilder();
    
    // 3. ๊ตฌํ˜„์ฒด ๋ฉ”์†Œ๋“œ ์‹คํ–‰
    Document document = builder.parse("src/main/resources/config.xml");
    System.out.println(document.getDocumentElement());
}

Spring Framework

 

FactoryBean

FactoryBean์€ ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ, ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณต๋˜๋Š” ์Šคํ”„๋ง ๊ตฌ๋ฌธ์œผ๋กœ๋Š” ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด๋ฅผ Bean์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ์–ด๋Œ‘ํ„ฐ ์—ญํ• ์„ ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด๋ž€ ์ƒ์„ฑ์ž๊ฐ€ privateํ•œ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด ํ˜น์€ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ค๋Š” ๊ฐ์ฒด๊ฐ€ ์ด์— ํ•ด๋‹นํ•œ๋‹ค. 

 

์˜ˆ๋ฅผ ๋“ค๋ฉด ์•„๋ž˜ Ship ํด๋ž˜์Šค๋Š” ์‹ฑ๊ธ€ํ†ค ์ฒ˜๋ฆฌ๋œ ๊ฐ์ฒด์ด๋‹ค.

public class Ship {
    private static final Ship INSTANCE = new Ship();

    private String name = "Singleton_TurtleShip";
    private String color = "Green";
    private String logo = "\uD83D\uDC22";
 
    private Ship(){}
    
    public static Ship getInstance() {
        return INSTANCE;
    }
}

๋งŒ์•ฝ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ Bean์œผ๋กœ ํ™œ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด FactoryBean์„ ์ด์šฉํ•ด ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค. FactoryBean์˜ ๊ตฌํ˜„์ฒด(ShipFactory)๋ฅผ ๋งŒ๋“ค๊ณ  ๊ตฌํ˜„์ฒด๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜๋ฉด, ShipFactory์˜ getObject()์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์ตœ์ข…์ ์œผ๋กœ Bean์œผ๋กœ ๋“ฑ๋ก๋˜๊ฒŒ ๋œ๋‹ค.

์ฆ‰, ์—ฌ๊ธฐ์„œ FactoryBean์€ ์ถ”์ƒ ํŒฉํ† ๋ฆฌ์˜ AbstractFactory์— ํ•ด๋‹นํ•˜๊ณ  ShipFactory๋Š” ConcreteFactory์— ํ•ด๋‹นํ•œ๋‹ค.

public class ShipFactory implements FactoryBean<Ship> {
    @Override
    public Ship getObject() throws Exception {
        return Ship.getInstance();
    }
 
    @Override
    public Class<?> getObjectType() {
        return Ship.class;
    }
}

 

ํด๋ผ์ด์–ธํŠธ์—์„œ ์‹คํ–‰ ํ•ด๋ณด๋ฉด xml์— ๋“ฑ๋ก๋œ ์ •๋ณด์— ๋”ฐ๋ผ ApplicationContext๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์˜ฌ ๋–„ ShipFactory๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ ์–ป์–ด์˜ค๊ฒŒ ๋œ๋‹ค.

<!-- config.xml -->
<bean id="myShip" class="ShipFactory">

</bean>
public static void main(String[] args) throws Exception {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
    
    Ship myShip = applicationContext.getBean("myShip");
    System.out.println(myShip);
}

# ์ฐธ๊ณ ์ž๋ฃŒ

์ฝ”๋”ฉ์œผ๋กœ ํ•™์Šตํ•˜๋Š” GoF์˜ ๋””์ž์ธ ํŒจํ„ด - ๋ฐฑ๊ธฐ์„ 

https://refactoring.guru/design-patterns/abstract-factory

https://reactiveprogramming.io/blog/en/design-patterns/abstract-factory