CS_Step6 - 팩토리 메서드 패턴(Factory Method Pattern)

장선웅·2022년 7월 18일
0

팩토리 메서드 패턴?

  1. 어떤 상황에서 조건에 따라 객체를 다르게 생성해야할 때 사용하는 패턴.
  2. 사용자의 입력값에 따라 하는 일이 달라질 경우, 분기를 통해 특정 객체를 생성해야 하는데 이때, 팩토리라는 클래스에 위임하여 팩토리 클래스가 객체를 생성하도록 하는 방식이다.

간단히 말하면, 상위 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴을 의미한다.


1. 팩토리 메서드 패턴은 왜 사용할까?

예를 들어, 어느 한 회사(CompanyA)에서 과자A,과자B,과자C를 만들어낸다고 생각해보자.

//과자를 캡슐화하기 위한 추상 클래스
public abstract class Type {}
//과자 A 클래스 생성
public class 과자A extends Type{
	public 과자A(){
    	System.out.println("과자C 생성");
    }
}
//과자 B 클래스 생성
public class 과자B extends Type{
	public 과자B(){
    	System.out.println("과자B 생성");
    }
}
//과자 A 클래스 생성
public class 과자C extends Type{
	public 과자C(){
    	System.out.println("과자C 생성");
    }
}
//과자A,B,C를 만드는 CompanyA 클래스
public class CompanyA {
	//타입에 따른 과자를 만드는 메서드
	public Type createSnack(String type) {
    	//어느 과자를 만들지 저장할 변수
    	Type snackType = null;
        //조건에 의한 만들 과자 타입 지정
        switch (type){
            //과자A
            case "A":
                returnType = new 과자A();
                break;
            //과자A
            case "B":
                returnType = new 과자B();
                break;
            //과자C
            case "C":
                returnType = new 과자C();
                break;
        }
        return snackType;
    }
}
//User클래스 생성(main클래스)
public class User {
	public void main(String args[]) {
    	//CompanyA 객체 생성
    	CompanyA companyA = new CompanyA();
        //입력값에 따른 과자 생성
        companyA.createSnak("A"); //과자 A 객체 생성
        companyA.createSnak("C"); //과자 C 객체 생성
    }
}

하지만 과자 A,B,C를 만드는 회사가 늘어난다고 가정해보도록 하자.

//과자A,B,C를 만드는 CompanyB 클래스
public class CompanyB {
	//타입에 따른 과자를 만드는 메서드
	public Type createSnack(String type) {
    	//어느 과자를 만들지 저장할 변수
    	Type snackType = null;
        //조건에 의한 만들 과자 타입 지정
        switch (type){
            //과자A
            case "A":
                returnType = new 과자A();
                break;
            //과자A
            case "B":
                returnType = new 과자B();
                break;
            //과자C
            case "C":
                returnType = new 과자C();
                break;
        }
        return snackType;
    }
}
//과자A,B,C를 만드는 CompanyC 클래스
public class CompanyC {
	//타입에 따른 과자를 만드는 메서드
	public Type createSnack(String type) {
    	//어느 과자를 만들지 저장할 변수
    	Type snackType = null;
        //조건에 의한 만들 과자 타입 지정
        switch (type){
            //과자A
            case "A":
                returnType = new 과자A();
                break;
            //과자A
            case "B":
                returnType = new 과자B();
                break;
            //과자C
            case "C":
                returnType = new 과자C();
                break;
        }
        return snackType;
    }
}

이처럼 중복 코드가 발생한다. 또한 이는 객체를 생성하는 일은 객체간의 결합도를 강하게 만들며, 객체간의 결합도가 높아진다면, 유지보수가 어려워진다.


2. 팩토리 메서드 패턴 구현 방법

팩토리 클래스(SnackCompanyFactory)를 정의한 뒤, 객체 생성이 필요한 클래스(Company)에서 팩토리 객체를 생성하여 분기에 따른 객체 생성 메서드를 호출한다.

//SnackCompanyFactory 클래스
public class SnackCompantFactory {
	//타입에 따른 과자를 만드는 메서드
    public Type createSnack(String type){
        Type snackType = null;
        switch (type){
        	//과자A
            case "A":
                returnType = new 과자A();
                break;
        	//과자B
            case "B":
                returnType = new 과자B();
                break;
        	//과자C
            case "C":
                returnType = new 과자C();
                break;
        }
        return snackType;
    }
}
//만드는 CompanyA 클래스
public class CompanyA {
    public Type createSnack(String type){
        SnackCompanyFactory factory = new TypeFactory();
        Type returnType = factory.createSnack(type);
        return snackType;
    }
}

이처럼 구현한다면, CompanyA,CompanyB,CompanyC에서 하던 객체 생성을 SnackCompanyFactory에서 한다. 그리고 CompanyA는 SnackCompanyFactory 클래스를 사용해서 객체를 생성한다.


3. 팩토리 메서드 패턴의 장/단점

장점

  1. 객체들이 하나의 팩토리 클래스에서 생성되기 때문에, 객체들의 변경에 대응하기 쉽다.
  2. 기존 코드를 수정하지 않고, 새로운 인스턴스를 다른방법으로 생성하도록 확장할 수 있다.
  3. 프로그램 내에서 동일한 객체의 호출이 잦을 경우, 성능을 높일 수 있다.
  4. 메서드로 작동하기 때문에, 리턴 값을 가지며, 이를 이용해 여러 상황에서 다른 객체를 반환할 수 있다.
  5. 코드가 간결해 진다.

단점

  1. 계속해서 새로운 하위 클래스를 정의하기 때문에, 코드가 길어지며, 복잡해질 수 있다.
profile
개발을 꿈꾸는 초짜

0개의 댓글