2 분 소요



팩토리 패턴(factory pattern)은 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴이자, 상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대 역할을 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴이다.

상위 클래스와 하위 클래스가 분리 되기 때문에 느슨한 결합을 가지며 상위 클래스에선 인스턴스 생성 방식에 대해 전혀 알 필요가 없기 때문에 더 많은 유연성을 갖게 된다.

그리고 객체 생성 로직이 따로 떼어져 있기 때문에 코드 리팩터링을 실시 하더라도 한 곳만 고칠 수 있게 되니 유지 보수성이 탁월하다.

예를 들어, 식빵 레시피, 크림빵 레시피, 피자빵 레시피라는 구체적인 내용이 들어 있는 하위 클래스가 상위로 전달되고, 상위 클래스인 뚜레쥬르에서 이 레시피들을 토대로 식빵 등을 생산하는 생산 공정을 생각하면 된다.



이를 자바 코드로 구현해보았다.



package bak;

import java.io.BufferedReader;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;


abstract class breads {
    public abstract int getPrice();

    @Override
    public String toString() { //클래스를 인스턴스화 
        return "Hi, this bread is " + this.getPrice();
    }

}
class TousLesJours {
    public static breads getBread(String type, int price) {
        if ("Cream".equalsIgnoreCase(type)) return new Cream(price);
        else if ("Pizza".equalsIgnoreCase(type)) return new
                Pizza(price);
        else {
            return new DefaultBread();
        }

    }
}

class DefaultBread extends breads{
    private int price;

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


    @Override
    public int getPrice() {
        return this.price;
    }

}

class Cream extends breads {
    private int price;


    public Cream(int price) {
        this.price = price;
    }
    @Override
    public int getPrice() {
        return this.price;
    }

}

class Pizza extends breads {
    private int price;

    public Pizza(int price) {
        this.price = price;
    }

    @Override
    public int getPrice() {
        // TODO Auto-generated method stub
        return this.price;
    }


}


public class Main {

    public static void main(String[] args) {
        breads piz = TousLesJours.getBread("Pizza",4000);
        breads cre = TousLesJours.getBread("Cream", 3000);
        System.out.println("Factory pizza ::  " + piz );
        System.out.println("Factory cream :: " + cre);






    }

}



크림빵 레시피를 통해(class Cream extends breads) 뚜레쥬르 공장(TousLesJours) 에서 , 빵 (Bread) 를 최종적으로 만들어낸다( abstract class breads)

지금 보면 if(“Cream”.equalsIgnoreCase(type))를 통해 문자열 비교 기반으로 로직이 구성되어있다. 이는 Enum 혹은 Map을 이용하여 If 를 쓰지 않고도 매핑해서 사용할 수 있다.



Enum을 이용한 Factory Method



이는 Factory Method 패턴의 단점을 보완한다.

기본적으로 Factory Method 패턴과 마찬가지로 객체의 생성을 담당하는 메소드를 구현하는 패턴이다. 이와 함께 Factory Method를 구현한 객체를 생성하기 위해 Singleton을 사용해야 하는 문제점을 Enum의 특성을 이용하여 해결한다



import java.io.*;
import java.util.*;

interface breads {
   public abstract int getPrice();

   @Override
   public String toString();
}

enum TousLesJours {
   Cream {
      @Override
      public breads getBread(int price) {
         return new Cream(price);
      }
   },

   Pizza {
      @Override
      public breads getBread(int price) {
         return new Pizza(price);
      }
   };

   public abstract breads getBread(int price);
}

class DefaultBread implements breads {
   private int price;

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

   @Override
   public int getPrice() {
      return this.price;
   }
}

class Cream implements breads {
   private int price;

   public Cream(int price) {
      this.price = price;
   }

   @Override
   public int getPrice() {
      return this.price;
   }

   @Override
   public String toString() {
      return "Hi, this bread is " + this.getPrice();
   }
}

class Pizza implements breads {
   private int price;

   public Pizza(int price) {
      this.price = price;
   }

   @Override
   public int getPrice() {
      return this.price;
   }

   @Override
   public String toString() {
      return "Hi, this bread is " + this.getPrice();
   }
}

public class Main {

   public static void main(String[] args) {
      breads piz = TousLesJours.Cream.getBread(4000);
      breads cre = TousLesJours.Pizza.getBread(3000);
      System.out.println("Factory pizza :: " + piz.toString());
      System.out.println("Factory cream :: " + cre.toString());
   }
}

댓글남기기