서론
오늘은 팩토리 패턴에 대해 알아보려고 한다.
헤드퍼스트 디자인패턴 책을 너무나 재미있게 읽고 있다. 알기 쉽게 그림이나 예제들을 통해 확인해 볼 수 있고 설명도 잘 되어있는 느낌이 많이 들었다.
사람마다 좋아하는 책 스타일은 다르겠지만… 나와 같은 성향인 분들에게는 한 번쯤은 꼭 읽어봐도 좋을 것 같다고 이야기하고 싶은 책이랄까…?
거두절미하고 시작해 보겠다.
팩토리 패턴의 학습목표부터 살펴보겠다.
- 느슨한 결합으로 객체지향 디자인을 만들어보자!
- new 연산자를 사용한다고 해서 새로운 객체가 만들어지지 않는다.
- 객체의 인스턴스를 만드는 작업을 공개하면 결합적인 문제가 발생할 수 있다.
- 팩토리 패턴은 불필요한 의존성을 없애서 결합 문제를 해결할 수 있다.
new 연산자
new 연산자는 자바의 뼈대를 이루는 연산자이기에, 당연히 안 쓸 수 없다.
new 자체는 문제가 없지만 사용했을 시, 변화에 항상 조심해야 한다.
구상클래스를 많이 사용하면 새로운 구상 클래스가 추가될 때마다 코드를 고쳐야 하기에, 수많은 문제가 생긴다.
즉, 변경에 닫혀 있는 코드가 될 수 있다.
새로운 구상 형식을 써서 확장해야 할 때는 어떻게 해서든 다시 열 수 있게 만들어야 한다. ( OCP 원칙! )
팩토리
객체를 생성하고 처리하는 클래스
앞으로 여러 팩토리를 체크하기 전, 해당 개념을 기억하고 보시면 더 도움이 되지 않을까 싶다.
간단한 팩토리 ( Simple Factory )
- 디자인 패턴이라기보단 프로그래밍에서 자주 쓰이는 관용구에 더 가깝다.
- 가~끔 위 간단한 팩토리를 “팩토리 패턴”이라고 부르는 사람들도 있는데 그때마다 그건 아니라고 속삭여보자
잠깐 짚고 넘어가야 할 점
디자인 패턴을 이야기할 때, “인터페이스를 구현한다.”라는 표현이 나오는데
이는 클래스선언 때 implements를 사용하여 클래스를 만든다라고 생각하면 절대 안 된다.
일반적으로 어떤 상위 형식(클래스, 인터페이스)에 있는 구상 클래스는 그 상위 형식의 ‘인터페이스를 구성하는’ 클래스라고 생각하면 된다.
자 그렇다면 예제를 통해 한번 살펴보겠다.
이 책에서는 피자를 만드는 거를 메인 주제로 잡고 진행하고 있었다. 그렇기에, “피자”라는 공통 주제를 가지고 팩토리 패턴에 대해서 풀어가 보고자 한다.
피자의 종류는 다양하다. 그렇기에, 처음에는 다음과 같이 코드를 구성할 수 있을 것이다.
하지만, 이렇게 작성하게 될 경우 피자의 종류가 늘어날 때마다 PizzaStore의 코드가 변경되어야 하고 결국 이는 OCP 원칙을 지키는 코드는 아니다.
그렇다면 어떻게 해야 할까?
먼저 OCP원칙을 지킬 수 있도록 캡슐화를 진행해 보겠다.
그렇다면?
이 부분이 해당이 될 것이다.
해당 부분은 인스턴스를 만드는 부분으로서, 해당 부분을 Factory로 따로 분리를 시켜보겠다.
- 여기서, 인스턴스를 만드는 클래스의 이름을 Factory라고 한다.
분리를 진행한 이후의 코드는 다음과 같을 것이다.
이렇게 인스턴스 생성 부분을 Factory로 분리하게 된다면, 이곳저곳에서 변경할 필요 없이 팩토리 클래스 하나만 고치면 된다.
그렇다면 장점만 가지고 있느냐? 사실 한계점도 존재한다.
한계점
- 팩토리가 클래스로 이뤄져 있기에 확장이 어렵다. 이는 (OCP에 위배)
- 위 내용 때문에 인터페이스로 변경하면 추상 팩토리패턴에서 하나의 product를 사용한 것과 유사
- 여기서 참고할 점은, 간단한 팩토리는 디자인 패턴이라기보다는 자주 쓰이는 관용구에 더 가깝다.
팩토리 메서드 패턴 ( Factory Method Pattern )
팩토리 메서드 패턴은 객체를 생성 시 필요한 인터페이스를 만드는데, 어떤 클래스의 인스턴스를 만들지 서브클래스에서 맡게 되는 것을 말한다.
즉, 위 예제를 기반으로 살펴보면 팩토리 역할을 PizzaStore가 아닌 서브클래스 ( Factory )에서 메서드를 Override 하여 수행한다는 내용이 된다.
여기서 중요한 건 사용하는 서브클래스에 따라 생산되는 객체의 인스턴스가 결정된다라는 걸 기억하자
실습의 경우는 포스팅이 너무 길어질 수 있기에, 작성 깃허브를 첨부하는 것으로 대체해 보고자 한다.
( 이론 외적으로 너무나 많이 차지할 것 같기에... )
그렇다면 이런 팩토리 메서드 패턴의 장단점에 대해 살펴보자
- 장점
- 팩토리 메서드 패턴의 가장 큰 장점은 OCP원칙을 지킬 수 있다.
- 다른 객체 없이 상속을 통해 구현하기에, 비교적 메모리를 아낄 수 있다.
- 중복코드 없이 재사용 가능
- 단점
- 간단한 기능을 사용할 때보다 많은 클래스를 정의해야 하기에 코드량이 증가한다.
추상 팩토리 패턴 ( Abstract Factory Pattern )
추상 팩토리 패턴은 구상 클래스에 의존하지 않고도 서로 연관되거나 의존적인 객체로 이뤄진 제품을 생산하는 인터페이스를 제공한다.
여기서 키워드는 제품과 인터페이스이다. 서로 관련 있는 객체를 묶어 조건에 따라 객체를 생성하도록 팩토리 클래스를 만들어 객체를 생성한다.
- 추상 팩토리 패턴에서 제공하는 인터페이스를 모든 팩토리가 상속받아야 한다.
- 상속받은 메서드를 구현할 때 추상 Product를 반환해야 한다.
- 클라이언트에서 추상 팩토리를 바탕으로 실제 팩토리를 선택해 생성해야 한다.
⇒ 만약, 간단한 팩토리를 인터페이스로 추상화하고 내부 메서드를 늘리면 추상 팩토리 패턴과도 완전히 같아진다.
그렇다면 추상 팩토리 패턴의 장단점은 어떻게 될까?
- 장점
- 팩토리 메서드 패턴에 비해 여러 개의 객체를 생성할 수 있다.
- 단점
- 제품을 추가하기 위해서는 인터페이스 내 메서드 추가를 해야 한다.
사실 구현 시에 대해 정리도 하였는데 작성 시 포스팅이 너무나 길어져 개념들을 하나씩 소개하기에 부족할 것 같아... 생략하였다.
구현 연습을 하였던 링크를 첨부하겠다.
https://github.com/JoeCP17/spring-study/tree/master/disignPattern/src/main/java/com/example/disign
이번에는 팩토리 패턴을 정리해 보았다. 이번 내용을 정리하며 마지막으로 3가지의 팩토리 패턴을 한눈에 보기 쉽게 정리하고 마무리해 보고자 한다.
간단한 팩토리 | 팩토리 메서드 패턴 | 추상 팩토리 패턴 | |
팩토리 생성 | 고수준 객체의 변수로 구성 | 상속으로 객체를 생성 | 고수준 객체의 변수로 구성 |
상속 | X | 인터페이스 Or 추상클래스 | 인터페이스 |
객체 생성 개수 | 1개 | 1개 | n개 |
'BOOK' 카테고리의 다른 글
[Design Pattern] Command Pattern 커맨드 패턴에 대해 알아보자! (0) | 2023.02.11 |
---|---|
[Design Pattern] Decorator Pattern 데코레이터 패턴에 대해 알아보자! (0) | 2023.01.14 |
[Design Pattern] Observer Pattern 옵저버 패턴에 대해 알아보자! (0) | 2023.01.07 |
[BOOK : 오브젝트 15장] 디자인 패턴과 프레임워크 (0) | 2022.12.18 |
[BOOK : 오브젝트 14장] 일관성 있는 협력 (0) | 2022.12.10 |