컴공생 누르지 마세요! 컴공생 울어요.

디자인 패턴 (2) 팩토리 패턴 본문

CS STUDY/디자인 패턴

디자인 패턴 (2) 팩토리 패턴

당도최고치악산멜론 2023. 3. 20. 19:57

팩토리 패턴

  • 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴
  • 상속 관계에 있는 두 클래스에서 상위클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴
  • 상위 클래스와 하위 클래스가 분리 ➡️ 느슨한 결합
  • 상위 클래스에서는 인스턴스 생성 방식에 대해 전혀 알 필요 없음 ➡️ 더 많은 유연성을 갖게 됨
  • 객체 생성 로직이 따로 떨어져 있기 때문에 코드를 리팩터링하더라도 한 곳만 고칠 수 있게 됨 ➡️ 유지보수성 증가
  • ex) 라떼 레시피, 아메리카노 레시피, 우유 레시피라는 하위 클래스가 컨베이어 벨트를 통해 전달되고, 상위 클래스인 바리스타 공장에서 이 레시피들을 토대로 라떼 등을 생산

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

  • new Object()로 구현 가능
  • 예시 1)
  • 숫자나 문자열을 전달함에 따라 다른 타입의 객체 생성
  • 전달받은 값에 따라 다른 객체를 생성하며, 인스턴스의 타입 결정
const num = new Object(42)
const str = new Object('abc')
num.constructor.name; // Number
str.constructor.name; // String
  • 예시 2) 커피 팩토리
    • CoffeFactory라는 상위 클래스가 중요한 뼈대 결정 & 하위 클래스인 LatteFactory가 구체적 내용 결정
    • LatteFactory에서 생성한 인스턴스를 CoffeFactory에 주입하고 있기 때문에 의존성 주입이라고 볼 수 있음
    • CoffeeFactory 클래스의 createCoffee() 메서드는 static 정적 메소드임
    • ➡️ 클래스의 인스턴스 없이 호출 가능 & 메모리 절약 가능 & 개별 인스턴스에 묶이지 않음 & 클래스 내의 함수 정의 가능
class CoffeeFactory {
    static createCoffee(type) {
        const factory = factoryList[type]
        return factory.createCoffee()
    }
}   
class Latte {
    constructor() {
        this.name = "latte"
    }
}
class Espresso {
    constructor() {
        this.name = "Espresso"
    }
} 

class LatteFactory extends CoffeeFactory{
    static createCoffee() {
        return new Latte()
    }
}
class EspressoFactory extends CoffeeFactory{
    static createCoffee() {
        return new Espresso()
    }
}
const factoryList = { LatteFactory, EspressoFactory } 
 
 
const main = () => {
    // 라떼 커피를 주문한다.  
    const coffee = CoffeeFactory.createCoffee("LatteFactory")  
    // 커피 이름을 부른다.  
    console.log(coffee.name) // latte
}
main()

자바의 팩토리 패턴

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
*/
  • 문자열 비교 기반으로 로직이 구성되어 있는데, Enum 또는 Map을 이용하여 if 문을 쓰지 않고 매핑해서 구성할 수도 있음
  • Enum
    • 상수의 집합 정의
    • 상수나 메서드 등을 넣어서 관리
    • 코드를 리팩터링할 때 해당 집합에 관한 로직 수정 시 이 부분만 수정하면 된다는 장점 존재

'CS STUDY > 디자인 패턴' 카테고리의 다른 글

디자인 패턴 (1) 싱글톤 패턴  (0) 2023.03.14
디자인 패턴 (0) 디자인 패턴  (0) 2023.03.14
Comments