객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴
※ 상위 클래스와 하위 클래스가 분리되기 때문에 느슨한 결합을 가지며, 상위 클래스에서는 인스턴스 생성방식에 대해 전혀 알 필요가 없기 때문에 더 많은 유연성을 갖게된다.
그리고 객체 생성 로직이 따로 떼어져 있기 때문에 코드를 리팩토링 하더라도 한 곳만 고칠 수 있게된다.
라떼 레시피와 아메리카노 레시피, 우유 레시피라는 구체적인 내용이 들어 있는 하위 클래스가 컨베이어 벨트를 통해 전달되고, 상위 클래스인 바리스타 공장에서 이 레시피들을 토대로 우유 등을 생산하는 생산공정을 만들어보자.
class Latte {
constructor() {
this.name = "latte"
}
}
class Espresso {
constructor() {
this.name = "Espresso"
}
}
class LatteFactory {
static createCoffee() {
return new Latte()
}
}
//Latte를 만드는 구체적인 방법이 들어가있으며, Latte를 리턴
class EspressoFactory {
static createCoffee() {
return new Espresso()
}
}
//Espresso를 만드는 구체적인 방법이 들어가있으며, Espresso를 리턴
class CoffeeFactory {
static createCoffee(type) {
const factory = factoryList[type]
return factory.createCoffee()
}
}
/*createCoffee라는 뼈대를 만들어서 어떤 type(latte, espresso, americano)
중에 하나의 인자를 받아서 인자를 기반으로 선택을 한다.
latteFactory인지, EspressoFactory인지 하위 클래스를 결정한다.
그리고 그 하위 클래스로부터 하위 클래스의 createCoffee라는 메소드를 호출한다.
*/
/*핵심은 coffeeFactory라는 메소드가 정해져있고, 그 메소드를 호출하는게 아니라,
Factory를 하나 정해서 그 메소드를 호출한다. 이게 팩토리 패턴이다.*/
const factoryList = { LatteFactory, EspressoFactory }
const main = () => {
// 라떼 커피를 주문한다.
const coffee = CoffeeFactory.createCoffee("LatteFactory") // 커피 이름을 부른다.
console.log(coffee.name) // latte
}
main()
/*여기에선 LatteFactory의 구체적인 메소드를 호출한다. */
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("Latte", 4000);
Coffee ame = CoffeeFactory.getCoffee("Americano", 3000);
System.out.println("Factory latte ::" + latte);
System.out.println("Factory ame ::" + ame);
}
}
/*
Factory latte ::Hi this coffee is 4000
Factory ame ::Hi this coffee is 3000
*/
요약 : 상위 클래스가 중요한 뼈대이고, 상위 클래스는 하위 클래스를 호출하는 것만. 객체 생성에 관한 구체적인 행동은 하위 클래스가 결정한다.