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

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

์ธํŒŒ_ 2022. 12. 7. 09:28

Factory-Method-pattern
Factory-Method-pattern

Factory Method Pattern

ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์€ ๊ฐ์ฒด ์ƒ์„ฑ์„ ๊ณต์žฅ(Factory) ํด๋ž˜์Šค๋กœ ์บก์Аํ™” ์ฒ˜๋ฆฌํ•˜์—ฌ ๋Œ€์‹  ์ƒ์„ฑํ•˜๊ฒŒ ํ•˜๋Š” ์ƒ์„ฑ ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.

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

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

 

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

Factory-Method-pattern
ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด์™€ ์ œํ’ˆ ๊ฐ์ฒด ๊ฐ„์— ๋А์Šจํ•œ ๊ฒฐํ•ฉ ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ๋‹ค

  • Creator : ์ตœ์ƒ์œ„ ๊ณต์žฅ ํด๋ž˜์Šค๋กœ์„œ, ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”์ƒํ™”ํ•˜์—ฌ ์„œ๋ธŒ ํด๋ž˜์Šค๋กœ ํ•˜์—ฌ๊ธˆ ๊ตฌํ˜„ํ•˜๋„๋กœ ํ•จ
    • ๊ฐ์ฒด ์ƒ์„ฑ ์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ(someOperartion) : ๊ฐ์ฒด ์ƒ์„ฑ์— ๊ด€ํ•œ ์ „์ฒ˜๋ฆฌ, ํ›„์ฒ˜๋ฆฌ๋ฅผ ํ…œํ”Œ๋ฆฟํ™”ํ•œ ๋ฉ”์†Œ๋“œ
    • ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ(createProduct) : ์„œ๋ธŒ ๊ณต์žฅ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•  ๊ฐ์ฒด ์ƒ์„ฑ ์ถ”์ƒ ๋ฉ”์„œ๋“œ
  • ConcreteCreator : ๊ฐ ์„œ๋ธŒ ๊ณต์žฅ ํด๋ž˜์Šค๋“ค์€ ์ด์— ๋งž๋Š” ์ œํ’ˆ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ƒ์„ฑ ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•œ๋‹ค. ์ฆ‰, ์ œํ’ˆ ๊ฐ์ฒด ํ•˜๋‚˜๋‹น ๊ทธ์— ๊ฑธ๋งž๋Š” ์ƒ์‚ฐ ๊ณต์žฅ ๊ฐ์ฒด๊ฐ€ ์œ„์น˜๋œ๋‹ค.
  • Product : ์ œํ’ˆ ๊ตฌํ˜„์ฒด๋ฅผ ์ถ”์ƒํ™”
  • ConcreteProduct : ์ œํ’ˆ ๊ตฌํ˜„์ฒด

์ •๋ฆฌํ•˜์ž๋ฉด, ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์€ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ณต์žฅ(Factory ๊ฐ์ฒด)์„ ๋งŒ๋“œ๋Š” ํŒจํ„ด์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์ง€๋Š” ๋ฏธ๋ฆฌ ์ •์˜ํ•œ ๊ณต์žฅ ์„œ๋ธŒ ํด๋ž˜์Šค์—์„œ ๊ฒฐ์ •ํ•œ๋‹ค.

๊ฒจ์šฐ ๊ฐ์ฒด ์ƒ์„ฑ ๊ฐ€์ง€๊ณ  ์ด๋Ÿฐ์‹์œผ๋กœ ๋ฒˆ๊ฑฐ๋กญ๊ฒŒ(?) ๊ตฌ์„ฑํ•˜๋Š” ์ด์œ ๋Š” ๊ฐ์ฒด๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜์— ์šฉ์ดํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ฐ์ฒด๋Š” ์‚ฌ๋žŒ / ์‚ฌ๋ฌผ๊ณผ ๊ฐ™์€ ์œ ํ˜•์˜ ํ˜•ํƒœ๊ฐ€ ๋ ์ˆ˜๋„ ์žˆ๊ณ , ์ „๋žต / ์ƒํƒœ ์™€ ๊ฐ™์€ ๋ฌดํ˜•์˜ ํ˜•ํƒœ๊ฐ€ ๋ ์ˆ˜๋„ ์žˆ๊ณ , ๊ณต์žฅ ๊ณผ ๊ฐ™์€ ์ค‘๊ฐ„ ์ƒ์„ฑ์ž ์—ญํ• ๋„ ํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. 
[ Template Method ํŒจํ„ด๊ณผ Factory Method ํŒจํ„ด๊ณผ์˜ ๊ด€๊ณ„ ]

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

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด ํ๋ฆ„

 

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

Factory-Method-pattern

 

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

// ์ œํ’ˆ ๊ฐ์ฒด ์ถ”์ƒํ™” (์ธํ„ฐํŽ˜์ด์Šค)
interface IProduct {
    void setting();
}

// ์ œํ’ˆ ๊ตฌํ˜„์ฒด
class ConcreteProductA implements IProduct {
    public void setting() {
    }
}

class ConcreteProductB implements IProduct {
    public void setting() {
    }
}

 

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

// ๊ณต์žฅ ๊ฐ์ฒด ์ถ”์ƒํ™” (์ถ”์ƒ ํด๋ž˜์Šค)
abstract class AbstractFactory {

    // ๊ฐ์ฒด ์ƒ์„ฑ ์ „์ฒ˜๋ฆฌ ํ›„์ฒ˜๋ฆฌ ๋ฉ”์†Œ๋“œ (final๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ๋ฐฉ์ง€, ํ…œํ”Œ๋ฆฟํ™”)
    final IProduct createOperation() {
        IProduct product = createProduct(); // ์„œ๋ธŒ ํด๋ž˜์Šค์—์„œ ๊ตฌ์ฒดํ™”ํ•œ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ์‹คํ–‰
        product.setting(); // .. ์ด๋ฐ–์˜ ๊ฐ์ฒด ์ƒ์„ฑ์— ๊ฐ€๋ฏธํ•  ๋กœ์ง ์‹คํ–‰
        return product; // ์ œํ’ˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ถ”๊ฐ€ ์„ค์ •ํ•˜๊ณ  ์™„์„ฑ๋œ ์ œํ’ˆ์„ ๋ฐ˜ํ™˜
    }

    // ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ : ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด ์ƒ์„ฑ ์ข…๋ฅ˜๋Š” ๊ฐ ์„œ๋ธŒ ํด๋ž˜์Šค์— ์œ„์ž„
    // protected ์ด๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€์— ๋…ธ์ถœ์ด ์•ˆ๋จ
    abstract protected IProduct createProduct();
}

// ๊ณต์žฅ ๊ฐ์ฒด A (ProductA๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜)
class ConcreteFactoryA extends AbstractFactory {
    @Override
    public IProduct createProduct() {
        return new ConcreteProductA();
    }
}

// ๊ณต์žฅ ๊ฐ์ฒด B (ProductB๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜)
class ConcreteFactoryB extends AbstractFactory {
    @Override
    public IProduct createProduct() {
        return new ConcreteProductB();
    }
}
์ตœ์ƒ์œ„ ๊ณต์žฅ ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์„ ์–ธํ•  ํ•„์š” ์—†๋‹ค.
Java 8 ๋ฒ„์ „ ์ดํ›„ ์ถ”๊ฐ€๋œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
Factory-Method-pattern

 

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

Factory-Method-pattern

class Client {
    public static void main(String[] args) {
        // 1. ๊ณต์žฅ ๊ฐ์ฒด ์ƒ์„ฑ (๋ฆฌ์ŠคํŠธ)
        AbstractFactory[] factory = {
                new ConcreteFactoryA(),
                new ConcreteFactoryB()
        };

        // 2. ์ œํ’ˆA ์ƒ์„ฑ (์•ˆ์—์„œ createProduct() ์™€ ์ƒ์„ฑ ํ›„์ฒ˜๋ฆฌ ์‹คํ–‰)
        IProduct productA = factory[0].createOperation();

        // 3. ์ œํ’ˆB ์ƒ์„ฑ (์•ˆ์—์„œ createProduct() ์™€ ์ƒ์„ฑ ํ›„์ฒ˜๋ฆฌ ์‹คํ–‰)
        IProduct productB = factory[1].createOperation();
    }
}

Factory-Method-pattern


ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด ํŠน์ง•

 

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

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

 

ํŒจํ„ด ์žฅ์ 

  • ์ƒ์„ฑ์ž(Creator)์™€ ๊ตฌํ˜„ ๊ฐ์ฒด(concrete product)์˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด์˜ ์ƒ์„ฑ ํ›„ ๊ณตํ†ต์œผ๋กœ ํ•  ์ผ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
  • ์บก์Аํ™”, ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด์˜ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ๊ฐ์ถœ ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ ์ค€์ˆ˜ : ๊ฐ์ฒด ์ƒ์„ฑ ์ฝ”๋“œ๋ฅผ ํ•œ ๊ณณ (ํŒจํ‚ค์ง€, ํด๋ž˜์Šค ๋“ฑ)์œผ๋กœ ์ด๋™ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํ• ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์›์น™์„ ๋งŒ์กฑ
  • ๊ฐœ๋ฐฉ/ํ์‡„ ์›์น™ ์ค€์ˆ˜ : ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ์œ ํ˜•์˜ ์ œํ’ˆ ์ธ์Šคํ„ด์Šค๋ฅผ ํ”„๋กœ๊ทธ๋žจ์— ๋„์ž…ํ•  ์ˆ˜ ์žˆ์–ด ์›์น™์„ ๋งŒ์กฑ (ํ™•์žฅ์„ฑ ์žˆ๋Š” ์ „์ฒด ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ์ด ๊ฐ€๋Šฅ)
  • ์ƒ์„ฑ์— ๋Œ€ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ๋ถ€๋ถ„๊ณผ ์ƒ์„ฑ์— ๋Œ€ํ•œ ๊ตฌํ˜„ ๋ถ€๋ถ„์„ ๋”ฐ๋กœ ๋‚˜๋‰˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํŒจํ‚ค์ง€ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐœ๋ณ„๋กœ ์—ฌ๋Ÿฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ํ˜‘์—…์„ ํ†ตํ•ด ๊ฐœ๋ฐœ

Factory-Method-pattern

 

ํŒจํ„ด ๋‹จ์ 

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

์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด๋Š” Factory Method ํŒจํ„ด

 

๋‹ค์–‘ํ•œ ์„ ๋ฐ• ํŒฉํ† ๋ฆฌ ๊ตฌ์„ฑํ•˜๊ธฐ 

์˜ˆ์ œ๋กœ ์„ ๋ฐ•(Ship) ์ œํ’ˆ์„ ๋งŒ๋“œ๋Š” ๋กœ์ง์„ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

 

ํด๋ฆฐํ•˜์ง€ ์•Š์€ ๋ฌธ์ œ์˜ ์ฝ”๋“œ โŒ

๊ฐ€์žฅ ์‹ฌํ”Œํ•œ ๋ฐฉ๋ฒ•์€ Ship ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ์„ ๋ฐ•๋„ ๋ถ„๊ธฐ๋ฌธ์œผ๋กœ ์ƒ์„ฑํ•˜๋„๋ก ํ•˜์˜€๋‹ค.

class Ship {
    String name, color, capacity;

    @Override
    public String toString() {
        return String.format("Ship { name: '%s', color: '%s', logo: '%s' }", name, color, capacity);
    }
}
public static Ship orderShip(String name, String email) {
    if (name == null) {
        throw new IllegalArgumentException("๋ฐฐ ์ด๋ฆ„์„ ์ง€์–ด์ฃผ์„ธ์š”");
    }
    if (email == null) {
        throw new IllegalArgumentException("์ด๋ฉ”์ผ์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”");
    }

    // ์„ ๋ฐ• ๊ฐ์ฒด ์ƒ์„ฑ
    Ship ship = new Ship();

    // ์„ ๋ฐ• ๊ฐ์ฒด ์ƒ์„ฑ ํ›„์ฒ˜๋ฆฌ
    ship.name = name;

    if (name.equalsIgnoreCase("ContainerShip")) {
        ship.capacity = "20t";
    } else if (name.equalsIgnoreCase("OilTankerShip")) {
        ship.capacity = "15t";
    }

    if (name.equalsIgnoreCase("ContainerShip")) {
        ship.color = "green";
    } else if (name.equalsIgnoreCase("OilTankerShip")) {
        ship.color = "blue";
    }

    System.out.println(ship.name + " ๋‹ค ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  " + email + "๋กœ ๋ฉ”์ผ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.");

    return ship;
}

public static void main(String[] args) {
    Ship containerShip = orderShip("ContainerShip", "inpa.naver.com");
    System.out.println(containerShip);

    Ship oilTankerShip = orderShip("OilTankerShip", "inpa.naver.com");
    System.out.println(oilTankerShip);
}

Factory-Method-pattern

ํ•˜์ง€๋งŒ ์œ„์˜ ๋ฐฉ๋ฒ•์€ ํด๋ฆฐํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์ด๋‹ค.

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

 

์‹ฌํ”Œ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ์ ์šฉํ•œ ์ฝ”๋“œ โญ•

์‹ฌํ”Œ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์ด๋ž€, ๊ฐ์ฒด ์ƒ์„ฑ์„ ๋‹ด๋‹นํ•˜๋Š” ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋ฅผ ์‹ฌํ”Œํ•˜๊ฒŒ ํ•˜๋‚˜๋งŒ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋งํ•œ๋‹ค.

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

Factory-Method-pattern

// ์ œํ’ˆ ๊ฐ์ฒด
class Ship {
    String name, color, capacity;

    @Override
    public String toString() {
        return String.format("Ship { name: '%s', color: '%s', logo: '%s' }\n", name, color, capacity);
    }
}

class ContainerShip extends Ship {
    ContainerShip() {
        name = "ContainerShip";
        capacity = "20t";
        color = "green";
    }
}

class OilTankerShip extends Ship {
    OilTankerShip() {
        name = "OilTankerShip";
        capacity = "15t";
        color = "blue";
    }
}
// ๊ณต์žฅ ๊ฐ์ฒด
class ShipFactory {

    final Ship orderShip(String name, String email) {
        validate(name, email);

        Ship ship = createShip(name); // ์„ ๋ฐ• ๊ฐ์ฒด ์ƒ์„ฑ

        sendEmailTo(email, ship);

        return ship;
    }

    private Ship createShip(String name) {
        Ship ship = null;
        if (name.equalsIgnoreCase("ContainerShip")) {
            ship = new ContainerShip();
        } else if (name.equalsIgnoreCase("OilTankerShip")) {
            ship = new OilTankerShip();
        }
        return ship;
    }

    private void validate(String name, String email) {
        if (name == null) {
            throw new IllegalArgumentException("๋ฐฐ ์ด๋ฆ„์„ ์ง€์–ด์ฃผ์„ธ์š”");
        }
        if (email == null) {
            throw new IllegalArgumentException("์ด๋ฉ”์ผ์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”");
        }
    }

    private void sendEmailTo(String email, Ship ship) {
        System.out.println(ship.name + " ๋‹ค ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  " + email + "๋กœ ๋ฉ”์ผ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.");
    }
}
class Client {
    public static void main(String[] args) {
        ShipFactory factory = new ShipFactory();

        Ship containerShip = factory.orderShip("ContainerShip", "inpa.naver.com");
        System.out.println(containerShip);

        Ship oilTankerShip = factory.orderShip("OilTankerShip", "inpa.naver.com");
        System.out.println(oilTankerShip);
    }
}

ํ•˜์ง€๋งŒ ์•„๋ฌด๋ฆฌ ๊ฐ์ฒด ์ƒ์„ฑ์„ ๊ณต์žฅ ํด๋ž˜์Šค๋กœ ์œ„์ž„ํ–ˆ๋”๋ผ๋„, ๊ณต์žฅ ํด๋ž˜์Šค ๋‚ด์—์„œ ์—ฌ์ „ํžˆ ๋ถ„๊ธฐ ๋กœ์ง์ด ์ž”์กดํ•ด ์žˆ๋‹ค.

์ฆ‰, ํ™•์žฅ์—” ์—ด๋ ค์žˆ๊ณ  ์ˆ˜์ •์—” ๋‹ซํžŒ ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ƒˆ๋กœ์šด ์ข…๋ฅ˜์˜ ๋ฐฐ๋ฅผ ๋งŒ๋“ ๋‹ค๊ฑฐ๋‚˜ ๋ฐฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ณต์ •์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉด์„œ๋„ ๊ธฐ์กด์— ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

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

 

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ์ ์šฉํ•œ ์ฝ”๋“œ โœ”๏ธ

์ž”์กดํ•ด ์žˆ๋Š” ๋ถ„๊ธฐ๋ฌธ์„ ์ œ๊ฑฐํ•˜๊ณ  ๊ฐ์ฒด ์ง€ํ–ฅ์œผ๋กœ ํŒฉํ† ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•ด๋ณด์ž.

๋จผ์ € ShipFactory ํด๋ž˜์Šค๋ฅผ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  Ship ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์„ ์ฑ…์ž„์ง€๋Š” createShip() ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋กœ ์ถ”์ƒํ™” ์‹œํ‚จ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์„ ๋ฐ• ์ข…๋ฅ˜์— ๋งž๊ฒŒ ShipFactory ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ์„œ๋ธŒ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋“ค์„ ๋งŒ๋“ค๊ณ  createShip() ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ ๊ฐ์ฒด ํŠน์ง•์— ๋งž๊ฒŒ ์žฌ์ •์˜ ํ•˜๋„๋ก ํ•œ๋‹ค.

์ฆ‰, orderShip() ๋ฉ”์„œ๋“œ์˜ ๊ณตํ†ต ์ฝ”๋“œ๋Š” ๋ƒ…๋‘๊ณ  Ship ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ์ž‘์—… ์ฝ”๋“œ๋Š” ์„œ๋ธŒ ํด๋ž˜์Šค๊ฐ€ ๊ฒฐ์ •ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. (์–ด์ฐŒ ๋ณด๋ฉด ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ์™€ ๊ฒฐ์ด ๋น„์Šทํ•˜๋‹ค ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค)

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

Factory-Method-pattern

class Ship {
    String name, color, capacity;

    @Override
    public String toString() {
        return String.format("Ship { name: '%s', color: '%s', logo: '%s' }\n", name, color, capacity);
    }
}

class ContainerShip extends Ship {
    ContainerShip(String name, String capacity, String color) {
        this.name = name;
        this.capacity = capacity;
        this.color = color;
    }
}

class OilTankerShip extends Ship {
    OilTankerShip(String name, String capacity, String color) {
        this.name = name;
        this.capacity = capacity;
        this.color = color;
    }
}
abstract class ShipFactory {

    // ๊ฐ์ฒด ์ƒ์„ฑ ์ „์ฒ˜๋ฆฌ / ํ›„์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ (์ƒ์† ๋ถˆ๊ฐ€)
    final Ship orderShip(String email) {
        validate(email);

        Ship ship = createShip(); // ์„ ๋ฐ• ๊ฐ์ฒด ์ƒ์„ฑ

        sendEmailTo(email, ship);

        return ship;
    }

    // ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ
    abstract protected Ship createShip();

    private void validate(String email) {
        if (email == null) {
            throw new IllegalArgumentException("์ด๋ฉ”์ผ์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”");
        }
    }

    private void sendEmailTo(String email, Ship ship) {
        System.out.println(ship.name + " ๋‹ค ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  " + email + "๋กœ ๋ฉ”์ผ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.");
    }
}

class ContainerShipFactory extends ShipFactory {
    @Override
    protected Ship createShip() {
        return new ContainerShip("ContainerShip", "20t", "green");
    }
}

class OilTankerShipFactory extends ShipFactory {
    @Override
    protected Ship createShip() {
        return new OilTankerShip("OilTankerShip", "15t", "blue");
    }
}
class Client {
    public static void main(String[] args) {
        // ์ „์šฉ ์„ ๋ฐ• ์ƒ์‚ฐ ๊ณต์žฅ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์„ ๋ฐ•์„ ์ƒ์„ฑ
        Ship containerShip = new ContainerShipFactory().orderShip("inpa.naver.com");
        System.out.println(containerShip);

        Ship oilTankerShip = new OilTankerShipFactory().orderShip("inpa.naver.com");
        System.out.println(oilTankerShip);
    }
}

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

 

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

// ์ œํ’ˆ ๊ฐ์ฒด
class BattleShip extends Ship {
    BattleShip(String name, String capacity, String color) {
        this.name = name;
        this.capacity = capacity;
        this.color = color;
    }
}

// ์ œํ’ˆ์„ ์ƒ์„ฑํ•˜๋Š” ๊ณต์žฅ ๊ฐ์ฒด
class BattleShipFactory extends ShipFactory {
    @Override
    protected Ship createShip() {
        return new BattleShip("BattleShip", "10t", "black");
    }
}

 

ํŒฉํ† ๋ฆฌ ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†คํ™” ํ•˜๊ธฐ ๐Ÿ› ๏ธ

๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณต์žฅ ๊ฐ์ฒด๋Š” ์—ฌ๋Ÿฌ๊ฐœ ์žˆ์„ ํ•„์š”์„ฑ์ด ์—†๋‹ค.

๋”ฐ๋ผ์„œ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ์œ ์ผํ•œ ์ธ์Šคํ„ด์Šค๋กœ ๋งŒ๋“ค์–ด ๋‘๋Š” ๊ฒƒ์ด ๋ฒ ์ŠคํŠธ ์ดˆ์ด์Šค์ด๋‹ค.

Factory-Method-pattern

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

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

Factory-Method-pattern
Factory-Method-pattern

class ContainerShipFactory extends ShipFactory {

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

    @Override
    protected Ship createShip() {
        return new ContainerShip("ContainerShip", "20t", "green");
    }
}

class OilTankerShipFactory extends ShipFactory {

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

    @Override
    protected Ship createShip() {
        return new OilTankerShip("OilTankerShip", "15t", "blue");
    }
}

class Client {
    public static void main(String[] args) {
        // ์ „์šฉ ์„ ๋ฐ• ์ƒ์‚ฐ ๊ณต์žฅ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์„ ๋ฐ•์„ ์ƒ์„ฑ
        Ship containerShip = ContainerShipFactory.getInstance().orderShip("inpa.naver.com");
        System.out.println(containerShip);

        Ship oilTankerShip = OilTankerShipFactory.getInstance().orderShip("inpa.naver.com");
        System.out.println(oilTankerShip);
    }
}

 

์ตœ์ƒ์œ„ ํŒฉํ† ๋ฆฌ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌ์„ฑํ•˜๊ธฐ ๐Ÿ› ๏ธ

์ตœ์ƒ์œ„ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋Š” ๋ฐ˜๋“œ์‹œ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์„ ์–ธํ•  ํ•„์š” ์—†๋‹ค.

Java 8 ๋ฒ„์ „ ์ดํ›„ ์ถ”๊ฐ€๋œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ์™€ Java 9 ๋ฒ„์ „ ์ดํ›„ ์ถ”๊ฐ€๋œ private ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ทธ๋Œ€๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

interface ShipFactory {

    // java8์— ์ถ”๊ฐ€๋œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ
    default Ship orderShip(String email) {
        validate(email);

        Ship ship = createShip(); // ์„ ๋ฐ• ๊ฐ์ฒด ์ƒ์„ฑ

        sendEmailTo(email, ship);

        return ship;
    }

    // ํŒฉํ† ๋ฆฌ ์ถ”์ƒ ๋ฉ”์„œ๋“œ
    Ship createShip();
	
    // java9์— ์ถ”๊ฐ€๋œ private ๋ฉ”์„œ๋“œ
    private void validate(String email) {
        if (email == null) {
            throw new IllegalArgumentException("์ด๋ฉ”์ผ์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”");
        }
    }

    private void sendEmailTo(String email, Ship ship) {
        System.out.println(ship.name + " ๋‹ค ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  " + email + "๋กœ ๋ฉ”์ผ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.");
    }
}

์‹ค๋ฌด์—์„œ ์ฐพ์•„๋ณด๋Š” Factory Method ํŒจํ„ด

 

Java

๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์— ๋”ฐ๋ผ ๋˜๋Š” ๋ฉ”์„œ๋“œ์— ๋”ฐ๋ผ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋‹จ์ˆœํ•œ ๋ฒ„์ „์˜ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์œผ๋กœ์„œ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด๊ณผ๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅด๋‹ค.

  • java.util.Calendar ์˜ getInstance()
  • java.util.ResourceBundle ์˜ getBundle()
  • java.text.NumberFormat ์˜ getInstance()
  • java.nio.charset.Charset ์˜ forName()
  • java.net.URLStreamHandlerFactory ์˜ createURLStreamHandler(String)
  • java.util.EnumSet ์˜ of()
  • javax.xml.bind.JAXBContext ์˜ createMarshaller() and other similar methods

 

NumberFormat์˜ getInstance()

  • ๊ตญ๊ฐ€  ๋˜๋Š” ํ™”ํ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ํ‘œํ˜„ ๋ฐฉ์‹์„ ์ปค๋ฒ„ํ•˜๊ธฐ ์œ„ํ•ด ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์œผ๋กœ ๋””์ž์ธ ๋˜์—ˆ๋‹ค.
  • NumberFormat์„ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋Š” DecimalFormat, ExponentialFormat ๋“ฑ์ด ์žˆ๋‹ค.
public static void main(String[] args) {
    // ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜
    NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();
    NumberFormat percentFormatter = NumberFormat.getPercentInstance();

    double x = 0.1;

    System.out.println(currencyFormatter.format(x)); // $0.10๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
    System.out.println(percentFormatter.format(x)); // 10%๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
}

 

Calendar์˜ getInstance()

  • getInstance()๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด Calendar ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ
  • Calendar๋Š” Gregorian ํ˜•์‹ Julian ํ˜•์‹์ด ์žˆ๋Š”๋ฐ, ์ด ๋‘๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ๋ชจ๋‘ ์ปค๋ฒ„ํ•˜๊ธฐ ์œ„ํ•ด ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์œผ๋กœ ๋””์ž์ธ ๋˜์—ˆ๋‹ค.
public static void main(String[] args) {
    // ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜
    System.out.println("Calendar ์˜ˆ์‹œ : ", Calendar.getInstance());
}

Spring Framework

 

BeanFactory

  • Object ํƒ€์ž…์˜ Product ๋ฅผ ๋งŒ๋“œ๋Š” BeanFactory ๋ผ๋Š” Creator
  • BeanFactory ๊ฐ€ Creator ์ธํ„ฐํŽ˜์ด์Šค์ด๊ณ  ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ClassPathXmlApplicationContext, AnnotationConfigApplicationContext ๊ฐ€ ConcreteCreator ์ด๋‹ค.
  • ์—ฌ๊ธฐ์„œ ๋„˜๊ฒจ์ฃผ๋Š” Product ๋Š” Object ํƒ€์ž…์ด๊ณ  ์ด๋ฅผ ๋„˜๊ฒจ ๋ฐ›๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ConcreateProduct ๊ฐ€ ๋œ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ ์Šค์บ”, bean ์„ค์ • ์–ด๋…ธํ…Œ์ด์…˜, xml ํŒŒ์ผ ๋“ฑ์˜  bean ๋“ค์ด ๊ฒฐ๊ตญ ConcreateProduct ์— ํ•ด๋‹น๋˜๋Š” ๊ฒƒ
  • ioc ์ปจํ…Œ์ด๋„ˆ์— ํ•ด๋‹น๋˜๋Š” ํด๋ž˜์Šค๊ฐ€ bean ํŒฉํ† ๋ฆฌ ์ธ๋ฐ ์ด๋ถ€๋ถ„์— ๋…น์•„์ ธ ์žˆ๋Š” ํŒจํ„ด์ด ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์ด๋‹ค.
// ์ปดํฌ๋„ŒํŠธ ์Šค์บ”, bean ์„ค์ • ์–ด๋…ธํ…Œ์ด์…˜, xml ํŒŒ์ผ ๋“ฑ์˜ bean ๋“ค์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ฃผ์–ด ConcreateProduct ๋ฅผ ๋ฐ˜ํ™˜
BeanFactory xmlFactory = new ClassPathXmlApplicationContext("config.xml");
String hello = xmlFactory.getBean("hello", String.class);

BeanFactory javaFactory = new AnnotationConfigApplicationContext(Config.class);
String hi = javaFactory.getBean("hi", String.class);

Factory Method ๋ณ€ํ˜• ํŒจํ„ด

GOF ๋””์ž์ธ ํŒจํ„ด์€ 1995๋…„์— ์ „ํ˜•ํ™”๋œ ์ฝ”๋“œ ํŒจํ„ด์ด๋‹ค. ์‹œ๋Œ€๊ฐ€ ์ง€๋‚จ์— ๋”ฐ๋ผ ์ž๋ฐ” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋„ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์ด ์ถ”๊ฐ€๋˜์—ˆ๊ณ  ์ด๋ฅผ ์‘์šฉํ•ด ๊ธฐ์กด์˜ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ข€๋” ๊ฐœ์„ ์‹œํ‚จ ์ผ์ข…์˜ GOF ๋ณ€ํ˜• ํŒจํ„ด์ด ์กด์žฌํ•œ๋‹ค.

 

Enum Factory Method ํŒจํ„ด

ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋ฅผ ์ž๋ฐ” Enum์œผ๋กœ ๊ตฌ์„ฑํ•œ ํŒจํ„ด์ด๋‹ค.

 

[GOF+] ๐Ÿ’  Enum Factory Method ๋ณ€ํ˜• ํŒจํ„ด ์•Œ์•„๋ณด๊ธฐ

Enum Factory Method Pattern Enum Factory Method ๋ณ€ํ˜• ํŒจํ„ด์€ GOF์˜ Factory Method ํŒจํ„ด์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ„ด์ด๋‹ค. Factory Method ํŒจํ„ด์˜ ๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ ์ œํ’ˆ ๊ฐ์ฒด์˜ ๊ฐฏ์ˆ˜๋งˆ๋‹ค ๊ณต์žฅ ์„œ๋ธŒ ํด๋ž˜์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌ

inpa.tistory.com

 

Dinamic Facory ํŒจํ„ด

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

 

[GOF+] ๐Ÿ’  Dynamic Factory ๋ณ€ํ˜• ํŒจํ„ด ์•Œ์•„๋ณด๊ธฐ

Dynamic Factory Pattern Dynamic Factory ๋ณ€ํ˜• ํŒจํ„ด์€ GOF์˜ Factory Method ํŒจํ„ด์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ„ด์ด๋‹ค. ๊ธฐ์กด ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด ์˜ค๋ฆฌ์ง€๋‚  Factory Method ํŒจํ„ด์˜ ๊ฐ€์žฅ ํฐ ๋‹จ์ ์€ ์ œํ’ˆ ๊ฐ์ฒด์˜ ๊ฐฏ์ˆ˜๋งˆ๋‹ค

inpa.tistory.com


๋น„์Šทํ•œ ๋””์ž์ธ ํŒจํ„ด ๋น„๊ต

 

Factory Method vs Abstract Factory

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

Factory Method vs Template Method

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

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

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

https://refactoring.guru/ko/design-patterns/factory-method