Skip to content

Latest commit

 

History

History
139 lines (117 loc) · 4.57 KB

팩토리 패턴.md

File metadata and controls

139 lines (117 loc) · 4.57 KB

🏭 팩토리 패턴 (factory pattern)

객체를 만드는 부분을 Sub class에 맡기는 패턴

  • 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴

  • 상속 관계에 있는 두 클래스에서 상위 클래스중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴임

  • 상위 클래스하위 클래스가 분리되기 때문에 느슨한 결합을 가짐

  • 상위 클래스에서는 인스턴스 생성 방식에 대해 전혀 알 필요가 없기 때문에 더 많은 유연성을 갖게 됩니다.

  • 객체 생성 로직이 따로 떼어져 있기 때문에 코드를 리팩터링하더라도 한 곳만 고칠 수 있게 되니 유지 보수성이 증가

  • 예를 들어 라떼 레시피와 아메리카노 레시피, 우유 레시피라는 구체적인 내용이 들어 있는 하위 클래스가 컨베이어 벨트를 통해 전달되고, 상위 클래스인 바리스타 공장에서 이 레시피들을 토대로 우유 등을 생산하는 생산 공정을 생각하면 됨


🏘️ 예시

✏️ 자바스크립트의 팩토리 패턴

  • 간단하게 new Object()로 구현할 수 있음

    const num = new Object(42);
    const str = new Object("abc");
    num.constructor.name; // Number
    str.constructor.name; // String
    • 숫자를 전달하거나 문자열을 전달함에 따라 다른 타입의 객체를 생성하는 것을 볼 수 있음
    • 즉, 전달받은 값에 따라 다른 객체를 생성하며 인스턴스의 타입 등을 정함

예시) 커피 팩토리를 기반으로 라떼 등을 생산하는 코드

class Latte {
  constructor() {
    this.name = "latte";
  }
}
class Espresso {
  constructor() {
    this.name = "Espresso";
  }
}

class LatteFactory {
  static createCoffee() {
    return new Latte();
  }
}
class EspressoFactory {
  static createCoffee() {
    return new Espresso();
  }
}

const factoryList = { LatteFactory, EspressoFactory };

class CoffeeFactory {
  static createCoffee(type) {
    const factory = factoryList[type];
    return factory.createCoffee();
  }
}
const main = () => {
  // 라떼 커피를 주문한다.
  const coffee = CoffeeFactory.createCoffee("LatteFactory");
  // 커피 이름을 부른다.
  console.log(coffee.name); // latte
};
main();
  • CoffeeFactory라는 상위 클래스가 중요한 뼈대를 결정하고 하위 클래스인 LatteFactory구체적인 내용을 결정하고 있음
  • 이는 의존성 주입이라고도 볼 수 있음
  • CoffeeFactory에서 LatteFactory의 인스턴스를 생성하는 것이 아닌 LatteFactory에서 생성한 인스턴스를 CoffeeFactory에 주입하고 있기 때문.
  • 또한, CoffeeFactory 클래스를 보면 static 키워드를 통해 `createCoffee()`` 메서드를 정적메서드로 선언한 것을 볼 수 있는데, 이렇게 정적 메서드로 정의하면 클래스를 기반으로 객체를 만들지 않고 호출이 가능하며, 해당 메서드에 대한 메모리 할당을 한 번만 할 수 있다는 장점이 있음

✏️ 자바의 팩토리 패턴

abstract class Coffee {
    public abstract int getPrice();

    @Override
    public String toString() {
        return "Hi this coffee is " + this.getPrice();
    }
}
class CoffeeFactory {
    public static Coffee getCoffee(String type, int price) {
        if ("Latte".equalsIgnoreCase(type)) return new Latte(price);
        else if ("Americano".equalsIgnoreCase(type)) return new Americano(price);
        else { return new DefaultCoffee();
        }
    }
}
class DefaultCoffee extends Coffee {
    private int price;

    public DefaultCoffee() {
        this.price -= 1;
    }

    @Override
    public int getPrice() {
        return this.price;
    }
}
class Latte extends Coffee {
    private int price;

    public Latte(int price) {
        this.price = price;
    }
    @Override
    public int getPrice() {
        return this.price();
    }
}
class Americano extends Coffee {
    private int price;

    public Americano(int price) {
        this.price = price;
    }
    @Override
    public int getPrice() {
        return this.price;
    }
}
public class HelloWorld {
    public static void main(String[] args) {
        Coffee latte = CoffeeFactory.getCoffee("Latee", 4000);
        Coffee ame = CoffeeFactory.getCoffee("Americano", 3000);
        System.out.println("Factory latte ::" + latte); // Hi this coffee is 4000
        System.out.println("Factory ame ::" + ame); // Hi this coffee is 3000
    }
}