Factory Method 패턴은 객체의 생성 방식과 관련된 디자인 패턴이다. 객체를 사용하는 클래스와 생성하는 클래스를 분리한다. 이를 통해 새로운 구현 클래스 추 시, 기존 프로그램 구조가 변경되지 않는다. 즉, 기존 코드는 바뀌지 않으면서 기능 확장에는 열려있도록 하는 패턴이다(SOLID OCP 원칙을 지킨다).
디자인 패턴 중에 Factory Method 패턴이 가장 이해하는데 오래 걸렸던 것 같다. 객체 생성을 위임하는 클래스를 따로 만드는 이유랑 예제가 안 와닿았던 것 같아 아래처럼 이전 방식(Factory 사용X, Simple Factory 방식)들도 정리해보았다.
위처럼 Factory Method Pattern을 알기 위해 우선 Factory 없이 객체 생성하는 방식과 Simple Factory 방식도 함께 정리하였다.
중요한 건 객체 생성을 담당하는Factory 클래스를 따로 만든다는 점이다. 이로 인해 확장에 열려 있으면서, 기존 코드를 변경하지 않게 된다❕ 아래에서 각각을 자세히 정리해보았다.
1. Factory 없이 객체 생성 시
💡 객체 생성 시 클라이언트단에서 구체화에 의존하는 방법
(Factory 사용X, 객체 사용부와 생성부가 분리되지 않음)
Product 클래스 → 인스턴스 생성하는데 사용함
publicinterfaceToy {voidplayToy();}publicclassTeddyBearimplementsToy { // toy 인스턴스 생성 시, 이 구체클래스로 직접 생성 @OverridepublicvoidplayToy() {System.out.println("인형 눈알 붙이기"); }}publicclassMiniCarimplementsToy { @OverridepublicvoidplayToy() {System.out.println("미니카 달리기"); }}
Client 클래스 (Product 사용하는 객체)
publicclassToyStore {publicToyorderToy(String toyType) { // toy 추가/변경 시, if문 코드도 변경된다.Toy toy;if (toyType.equals("TeddyBear")) { toy =newTeddyBear();elif (toyType.equals("MiniCar")) { toy =newMiniCar(); } }}
클라이언트 코드
// 생성한 Toy 인스턴스 사용ToyStore toyStore =newToyStore();toyStore.orderToy(newTeddyBear());
Toy 객체 생성 시, Factory 클래스 없이 Toy 구현 클래스를 통해 직접 생성한 경우이다. 이때 만약 새로운 Toy 종류를 추가하려면, ToyStore 클래스 코드 내부를 변경해주어야 한다.
이를 보완하기 위해 객체의 생성을 분리하여 담당하는 Factory 클래스를 사용한다. 우선 Simple Factory 방식 또한 OCP를 지키지 못하고 디자인 패턴이라 분류하지는 않지만, Factory Method 패턴을 이해하기 위한 전단계이므로 정리해보았다.
2. Simple Factory
💡 객체 생성용 서브 클래스(Factory)를 분리하는 방법
객체 생성하는 Factory 클래스를 따로 만드는 방법이다. ToyStore은 Factory를 통해 Toy를 생성한다. 단, ToyFactory 클래스 코드를 보면 OCP가 지켜지지 않음을 알 수 있다.
단, Simple Factory 방식은 새로운 구현 클래스를 추가하려면, 이 Factory 클래스의 코드 변경이 필요하다. 따라서 이러한 Simple Factory 방식은 OCP가 지켜지지 않고, 디자인 패턴이라 부르지 않는다. Factory Method 패턴을 이해하기 위한 중간 과정이라 볼 수 있다.
publicclassToyFactory { // 새로운 toy 추가 시 이 클래스 내부를 수정해주어야 함!publicToycreateToy(String toyType) {switch (toyType) {case TeddyBear:returnnewTeddyBear();case MiniCar:returnnewMiniCar();default:thrownewIllegalArgumentException(); } }}
// ToyStore에서 생성한 Toy 인스턴스 사용 시ToyFactory toyFactory =newToyFactory();ToyStore toyStore =newToyStore(toyFactory);toyStore.orderToy("TeddyBear");toyStore.orderToy("MiniCar");
이러한 Simple Factory 방식에서 구현체를 추가/변경하려면, Factory 클래스 내부 코드를 변경해야 한다. 다음의 Factory Method 방식은 기존 코드를 변경하지 않으면서 새로운 구현체를 추가할 수 있다.
3. 팩토리 메소드
💡 객체 생성용 Factory 클래스를 분리하고, 어떤 객체를 생성할지 서브 클래스가 결정하는 방식
객체를 생성하는 서브 클래스(Factory)를 만들어, 어떤 객체를 생성할지는 서브 클래스(Factory)가 결정한다. 기존 클래스에서는 객체 생성에 대한 정보를 가지지 않고, 서브 클래스(Factory)에서만 조작할 수 있다. 즉, 클래스의 생성과 사용을 분리하여 결합도를 낮춘다.