팩토리 메소드 패턴(Factory Method Pattern)
by youngjun._.1. 팩토리 메소드 패턴이란?
다양한 구현체 (Product)가 있고, 그 중에서 특정한 구현체를 만들 수 있는 다양한 팩토리(Creator)를 제공할 수 있다.
1-1. 정의(Definition)
1-1-1. 팩토리 패턴?
객체의 생성을 캡슐화 하는 패턴이다.
구체적인 객체의 생성 과정을 '팩토리'로 모듈화 하여 구체적인 부분이 아닌 추상적인 부분에 의존할 수 있도록 한다.
팩토리 패턴에는 팩토리 메소드 패턴과 추상 팩토리 패턴이 있다.
Pattern | 공통점 | 차이점 |
팩토리 메소드 패턴 | 객체의 생성부를 캡슐화하여 결합을 느슨하게 함 구체적인 타입에 의존하지 않도록 함 |
상속을 통해 서브 클래스에서 팩토리 메소드를 오버라이딩하여 객체의 생성부를 구현 |
추상 팩토리 패턴 | 객체의 집합을 생성하기 위한 정의를 추상체에 위치시키고 하위의 구현체에서 세부적인 집합 생성 과정을 구현 (Fatory Method를 이용해 구현) |
먼저 팩토리 메소드 패턴을 살펴보자.
1-1-2. 팩토리 메소드 패턴?
부모(상위) 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며. 자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이기도 하다.
1-2. 사용 이유
객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스에서 이루어지도록 하여 재정의 가능한 것으로 설계 하지만, 복잡해지지 않게 한다.
- 생성할 객체 타입을 예측할 수 없을 때
- 생성할 객체를 기술하는 책임을 서브클래스에게 정의하고자 할 때
- 객체 생성의 책임을 서브클래스에 위임시키고 서브클래스에 대한 정보를 은닉하고자 할 때
1-3. 장점과 단점
1-3-1. 장점
- 기존 코드(인스턴스를 만드는 과정)를 수정하지 않고 새로운 인스턴스를 다른 방법으로 생성하도록 확장할 수 있다.
- Product 와 Creator 간의 커플링(결합)이 느슨함
- 확장에 열려있고 변경에 닫혀있는 객체지향 원칙을 적용했기 때문에 가능
- 확장 : 새로운 인스턴스 추가
- 변경 : 기존 코드를 수정
- 코드가 간결해진다.
- 병렬적 클래스 계층도를 연결하는 역할을 담당할 수 있음
✍🏻 팩토리 메소드 패턴을 적용할 때 참고
1. 자바 8의 인터페이스 default 메소드
- 인터페이스에 추상 메소드가 아닌 default 메소드를 통해 기능을 구현할 수 있게 되어서 상속받는 서브클래스의 중복코드를 제거할 수 있다.
2. 자바 9의 인터페이스의 private 메소드
- 기능 구현이 가능해지면서 인터페이스의 내부 로직을 private 메소드로 구현하면 읽기 좋은 코드로 작성할 수 있게 된다.
1-3-2. 단점
- 클래스가 많아진다. (클래스 계층도 커질 수 있다.)
- 제품 클래스가 바뀔 때마다 새로운 서브클래스를 생성해야 한다.
- 클라이언트가 creator 클래스를 반드시 상속해 Product를 생성해야 한다.
1-4. 실제 적용 예시
실제 자바코드에 어떻게 적용되어있는지 예시를 살펴보자.
1-4-1. 단순한 팩토리 패턴
매개변수의 값에 따라 또는 메소드에 따라 각기 다른 인스턴스를 리턴하는 단순한 버전 의 팩토리 패턴
java.util.Calendar#getInstance()
public class CalendarExample {
public static void main(String[] args) {
log.info("Calendar 예시 : {}", Calendar.getInstance());
}
}
- getInstance()를 호출할 때마다 새로운 Calendar 객체가 생성된다.
- Calendar는 Gregorian형식(우리가 현재 쓰는), Julian 형식이 있는데, 이 두가지 경우를 모두 커버하기 위해 팩토리 메소드 패턴으로 디자인 되었다.
싱글톤(singletone)패턴에서 사용되는 이름 같은데, naming이 약간 잘못 지어진 것 같다.
java.text.NumberFormat#getInstance()
BeanFactory xmlFactory = new ClassPathXmlApplicationContext("config.xml");
String hello = xmlFactory.getBean("hello", String.class);
BeanFactory javaFactory = new AnnotationConfigApplicationContext(Config.class);
String hi = javaFactory.getBean("hi", String.class);
- 국가에 따라 또는 화폐에 따라 다른 표현 방식을 커버하기 위해 팩토리 메소드 패턴으로 디자인 되었다.
- NumberFormat을 구현하는 클래스는 DecimalFormat, ExponentialFormat 등이 있다.
1-4-2. 스프링 BeanFactory
Object 타입의 Product를 만드는 BeanFacotry라는 Creator
BeanFactory factory = new XmlBeanFactory(
new InputStreamResource(
new FileInputStream("oraclejavacommunity.xml")));
OracleJavaComm ojc = (OracleJavaComm)factory.getBean("oracleJavaBean");
- xml 설정과 java 설정으로 읽어오는 방식이다.
- Product에 해당하는 것은 Object
- ConcreteProduct에 해당하는 것은 xml 또는 class Bean
1-5. 결론
팩토리 메소드 패턴을 사용하는 이유는 클래스간의 결합도를 낮추기 위한 것 같다.
결합도라는 것은 간단히 말해 클래스의 변경할 부분이 생겼을 때 얼마나 다른 클래스에도 영향을 주는가이다. 팩토리 메소드 패턴을 사용하는 경우 직접 객체를 생성해 사용하는 것을 방지하고 서브 클래스에 위임함으로써 보다 효율적인 코드 제어를 할 수 있고 의존성을 제거한다. 결과적으로 결합도 또한 낮출 수 있다.
Reference
'SoftwareEngineering' 카테고리의 다른 글
[구조 패턴] 플라이웨이트 패턴 (0) | 2021.12.30 |
---|---|
[구조 패턴] 데코레이터 패턴 (0) | 2021.12.23 |
[구조 패턴] 어댑터 패턴 (0) | 2021.12.15 |
빌더 패턴(Builder Pattern) (7) | 2021.12.10 |
[생성 패턴] 싱글톤 패턴(Singleton Pattern) (0) | 2021.11.25 |
블로그의 정보
개발하는만두
youngjun._.