본문 바로가기
Languages/디자인패턴

[Java] 팩토리 메서드(Factory Method) 패턴

by yoon_seon 2023. 6. 10.

Factory Method 패턴이란

Factory method 패턴은 부모 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며, 자식 클래스가 어떤 객체를 생성할지를 결정하도록 하는 객체지향 디자인 패턴이다. 부모 클래스 코드에 구체 클래스 이름을 감추기 위한 방법으로도 사용한다.

즉, 인스턴스를 생성하는 방법은 부모 클래스가 가지고 있고 상속을 통해 자식 클래스에서 실제로 동작하는 구현체를 작성하는 방법이다.

 

제품을 정의하는 Product 인터페이스

public interface Product {
    void use();
}
  • 제품을 사용한다는 행동을 정의했다.

 

제품을 생성하는 Factory 인터페이스

public interface Factory {
    Product createProduct(String name);
}
  • 제품의 이름을 입력받아 생성하고 제품을 반환하는 행동을 정의했다.

 

IDCard 제품

public class IDCard implements Product {
    private String owner;

    public IDCard(String owner) {
        this.owner = owner;
    }

    @Override
    public void use() {
        System.out.println(owner + "님의 카드를 사용합니다.");
    }
}
  • 상품을 정의한 Product 인터페이스의 use 메서드를 override하여 구현한다.

 

IDCard를 만드는 IDCardFactory

public class IDCardFactory implements Factory {
    @Override
    public IDCard createProduct(String name) {
        return new IDCard(name);
    }
}
  • 제품을 생성하는 Factory 인터페이스의 createProduct 메서드를 orderride하여 구현한다.

 

패턴 적용 예제

import factory.Factory;
import factory.IDCardFactory;
import factory.Product;

public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product idCard1 = factory.createProduct("홍길동");
        Product idCard2 = factory.createProduct("한석봉");

        idCard1.use();
        idCard2.use();
    }
}
  • 추상화를 통해 구현했기 때문에 IDCard 및 IDCardFactory의 구현부가 변경되어도 main에서는 코드를 변경할 필요가 전혀 없다.
  • main에서 IDCard를 import 하지 않고 있지만 기능은 사용하고 있다. 따라서 main과 IDCard간의 결합도를 낮출 수 있다.

 

다음과 같이 Factory method 패턴을 수정해서 사용할 수도 있다.

 

IDCard

public class IDCard implements Product {
    private String owner;

    public IDCard(String owner) {
        this.owner = owner;
    }

    @Override
    public void use() {
        System.out.println(owner + "님의 카드를 사용합니다.");
    }
	
    // Factory 내부 클래스 추가
    public static class Factory {
        public static IDCard create(String owner){
            return new IDCard(owner);
        }
    }
}
  • 이전처럼 IDCardFactory 인터페이스를 생성하고 여러가지 기능들을 추상화 하는 것도 좋겠지만 생성하고자 하는 객체가 많아진다면 인터페이스를 생성하는데 제한이 있을 수 있다. 그래서 만들고자하는 객체 안에 기능을 정의하여 사용하는 방법으로도 자주 쓰인다.
  • IDCardFactory의 createProduct를 만들지 않고 IDCard안에 Factory 내부클래스를 생성해서 IDCard를 만드는 create 메서드를 생성했다.

 

패턴을 수정한 예제

import factory.Factory;
import factory.IDCard;
import factory.IDCardFactory;
import factory.Product;

public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product idCard1 = factory.createProduct("홍길동");
        Product idCard2 = factory.createProduct("한석봉");

        idCard1.use();
        idCard2.use();

        IDCard idCard3 = IDCard.Factory.create("한석봉");
        idCard3.use();
    }
}
  • 이전 예제와 달리 IDCard를 import하고 있어 결합도를 낮춘다는 장점은 사라졌지만 개발의 편의성을 위해서 Factory method패턴을 응용해서 사용할 수 있다.

 

정리

  • 추상화를 통해 구현하기 때문에 클래스가 수정되더라도 다른 클래스에 수정할 필요가 없으므로 변경에는 닫혀있고 확장에는 열려있는 OCP 원칙을 지킬 수 있다.
  • 구현체를 직접 import하지 않아 결합도를 낮출 수 있다.
  • 많은 클래스를 정의해야 하기 때문에 코드량이 증가한다는 단점이 있다.
  • Factory method패턴은 클래스간의 결합도를 낮추는 것이 목표이지만, 결합도를 낮춘다는 장점은 버리고 개발자의 목적에 맞게 수정하여 사용할 수도 있다.

'Languages > 디자인패턴' 카테고리의 다른 글

[Java] 옵저버(Observer) 패턴  (0) 2023.06.12
[Java] 데코레이터(Decorator) 패턴  (0) 2023.06.11
[Java] 어댑터(Adapter) 패턴  (0) 2023.06.10
[Java] 싱글톤(Singleton) 패턴  (0) 2023.06.10
[Java] 빌더(Builder) 패턴  (0) 2023.06.08

댓글