개발이슈/디자인패턴

팩토리 메소드 패턴2 (factory method pattern)

kalkin 2022. 8. 29. 13:42

구체적으로 어떤 인스턴스를 만들건지는 하위 클래스에서 정한다. 

 

예를들어, 추상클래스에서 기본 비지니스 로직을 정한 후 변경될수 있는 소지가 다분한 메소드나 기능은 

 

하위클래스에서 만들수 있도록 추상메서드를 이용한다. 

 

 

대표적인 팩토리 메서드 패턴을 가진 Calendar class를 한번 보자. 

 

 

java.util.Calendar.class 내의 Factory Method Pattern 의 예 

 private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }

case 문을 이용하여 

파라메터에 맞는 달력 class (BuddhistCalendar, JapaneseCalendar, GregorianCalendar)등으로 

분기처리해주는 모습을 볼수 있다. 

 

 

 

자 , 테스트를 한번 해보자. 

package factorymethod;

import java.util.Calendar;
import java.util.Locale;

public class TestCalendar {

    public static void main(String[] args) {

        System.out.println(Calendar.getInstance().getClass());
        System.out.println(Calendar.getInstance(Locale.forLanguageTag("th-TH-x-lvariant-TH")).getClass());
        System.out.println(Calendar.getInstance(Locale.forLanguageTag("ja-JP-x-lvariant-JP")).getClass());


    }
}

Locale 구분에 따라, 추상클래스를 구현한 서브클래스가 다르게 공급받는다. 

 

1. 장점

인터페이스나 추상클래스 등을 이용하여 OCP 에 준수하여 개발할수 있다. (객체간 느슨한 결합)

new로 객체 생성하지않고 주입을 사용함. (DI)

 

 

2. 단점.

클래스가 늘어남, (복잡해보일수 있음)

 

 

 

확장에 열려있고, 변경에 닫혀 있는 객체 지향원칙 ( OCP )

- 기존코드를 변경하지않으면서 새로운 기능을 확장 할 수 있어야함. 

 

 

자바8에 추가된 default 메서드.

- java8 이전에는 interface에는 추상메서드만 정의 할 수있었음 

추상클래스에서 하던일을 interface에서도 사용할 수 있게됨.