팩토리 메소드(Factory Method) 패턴

차동준·2022년 7월 18일
0

CS-디자인패턴

목록 보기
6/16
post-thumbnail

👨‍💻 팩토리란?


객체 생성을 처리하는 작업을
하나의 클래스로(팩토리 클래스)
만들어서 처리하는 방법



예시) 팩토리 예시


어떠한 옷가게가 있다고 하자.
편집샵, Gucci 매장, POLO 매장, ...

이 여러 종류의 옷가게에서는 원래
옷을 직접 만들어서 판매했다고 한다.

public class EditorShop {
	public Cloth makeCloth(String type) {
    	if (type == "shirt") {
        	return new Shirt();
        } else if (type == "pants") {
        	return new Pants();
        }
        return null;
    }
}

그렇게 되면, 어떤 문제가 발생할까?
만약 옷 만드는 방법이 바뀌었을 때,
아래 편집샵에 바뀐 코드를
모든 매장에 전부 알려줘서 적용해야 할 것이다.

public class EditorShop {
	public Cloth makeCloth(String type) {
    	if (type == "shirt") {
        	return new Shirt();
        } else if (type == "pants") {
        	return new Pants();
        } else if (type == "t-shirt") {
        	return new TShirt(); // 새로운 T 셔츠 만드는 방법 추가
        }
        return null;
    }
}

하지만, 간단한 팩토리(Simple Factory)를 사용한다면,
옷을 공장에서 만들어서 매장에서는 판매만 하면 되기 때문에,
옷 만드는 방법이 바뀌더라도 공장에서만 알고있으면 된다.

아래와 같이 간단한 Factory 클래스를 만들고,

public class SimpleClothFactory {
	public Cloth makeCloth(String type) {
    	if (type == "shirt") {
        	return new Shirt();
        } else if (type == "pants") {
        	return new Pants();
        } else if (type == "t-shirt") {
        	return new TShirt(); // 새로운 T 셔츠 만드는 방법 추가
        }
        return null;
    }
}

아래와 같이 모든 매장에 해당 공장을 연결하고
옷을 받아오는 함수에 팩토리 클래스의
옷 생성 메소드를 이용하여 옷을 받아오게 되면
각 매장의 옷을 받아오는 코드를 고칠 필요가 없다.(OCP)

public class EditorShop {
	SimpleClothFactory factory;
    
	public EditorShop(SimpleClothFactory factory) {
    	this.factory = factory;
    }
    
    public Cloth getCloth(String type) {
    	return this.factory.makeCloth(type);
    }
}

public class GucciShop {
	SimpleClothFactory factory;
    
	public GucciShop(SimpleClothFactory factory) {
    	this.factory = factory;
    }
    
    public Cloth getCloth(String type) {
    	return this.factory.makeCloth(type);
    }
}

public class POLOShop {
	SimpleClothFactory factory;
    
	public POLOShop(SimpleClothFactory factory) {
    	this.factory = factory;
    }
    
    public Cloth getCloth(String type) {
    	return this.factory.makeCloth(type);
    }
}

사실상 팩토리 자체만으로는 디자인 패턴이라고 하기 보다는
자주 쓰는 관용적인 방식이라고 부르는 게 맞다.

우리가 알아야 하는 진짜 팩토리 패턴은
1. 팩토리 메소드 패턴(Factory Method Pattern)
2. 추상 팩토리 패턴(Abstract Factory Pattern)

이 두가지 이다.



👨‍💻 팩토리 메소드 패턴이란?


객체를 생성할 때 필요한 인터페이스를 생성하고,
어떤 인스턴스 객체를 생성할지는 서브 클래스에서 결정
할 수 있게 추상 메소드로 남겨놓는 패턴



예시) 팩토리 메소드 패턴 예시


만약, 위 예시처럼 옷을 판다면
모든 옷에 다 같은 상표 같은 쇼핑백에 담겨져서 나가게 된다.
하지만 우리가 어떤 민족인가, 구찌 로고 하나에 50을 태우는 그런 민족이다.

옷에도 상표, 재질, 모든 것들이 다 다르기 때문에 세분화할 필요가 있다는 것이다.

그렇기 때문에 우리는 옷가게라는 좀더 상위 클래스나 인터페이스를 구현하고 옷 객체를 생성하는 메소드를 추상메소드로 설정하게 되면 각각의 옷가게에 맞는 옷 객체 생성 메소드를 세분화할 수 있게 된다.

public abstract class ClothStore {
	public Cloth getCloth(String type) {
    	Cloth cloth = makeCloth(type);
        cloth.pack();
        cloth.box();
        
        return cloth;
    }
    
    public abstract Cloth makeCloth(String type);
}

위와 같이 makeCloth 메소드를 서브 클래스에서 구현하도록 만들어 주는 것이다. 물론 이 방법은 옷 객체를 만드는 방법이 더욱 세분화될 필요가 있을 때 사용하는 것이다.

public class GucciStore extends ClothStore {
	Cloth makeCloth(String type) {
    	if (type == "shirt") {
        	return new GucciShirt();
        } else if (type == "pants") {
        	return new GucciPants();
        } else if (type == "t-shirt") {
        	return new Gucci_T_Shirt(); 
        }
        return null;
    }
}

public class POLOStore extends ClothStore {
	Cloth makeCLoth(String type) {
    	if (type == "shirt") {
        	return new POLO_Shirt();
        } else if (type == "pants") {
        	return new POLO_Pants();
        } else if (type == "t-shirt") {
        	return new POLO_T_Shirt(); 
        }
        return null;
    }
}

이렇게 하면, 어떠한 매장을 선택하느냐에 따라
옷의 종류가 바뀌게 되는 것이다.
일반 팩토리 클래스를 만들어서 구현하는 것 보다는
변경 사항이 좀 더 많은 것 같다.
애초에 매장별로 세분화할 게 더 많아지는 느낌이다.

public static void main(String[] args) {
	ClothStore store = new GucciStore();
    store.getCloth(); // 구찌 옷 받음
    
    ClothStore store2 = new POLOStore();
    store.getCloth(); // 폴로 옷 받음
}

결론으로, 방금 구현한 상위의 추상클래스(ClothStore)는 생산자(Creator) 클래스라고 하고,

추상클래스를 상속받아 객체 생성 메서드를 구현한 서브클래스(GucciStore, POLOStore 등)을 제품(Product) 클래스라고 한다.


👨‍💻 추상 팩토리 패턴이란?


연관되거나 의존적인 객체로 이루어진 제품군을 생산하는
인터페이스를 만들고, 서브클래스에서 이를 구현하는 패턴

추상 팩토리는 우리가 제일 흔히 알고있는 인터페이스의 사용방법일 수도 있다.


예시) 추상 팩토리 패턴 예시


위의 예시를 다시 가져와서,
Cloth라는 클래스를 직접적으로 설명한 적은 없지만,
옷에는 재질, 모양, 원산지, 등등이 있을 것이다.

따라서 Cloth는 구체적인 클래스로 만드는 것이 아니라,
ClothFactory 라는 인터페이스로 제공하고
이를 구현한 서브클래스에서 직접 구현해주는 것이 바로
추상 팩토리 패턴이다.

public interface ClothFactory {
	Material getMaterial();
    ClothShape getClothShape();
    MadeIn getMadeIn();
}
public class OwlCloth implements ClothFactory {
	public Material getMaterial() {
    	return new Material("이것은 울입니다");
    }
    
    public ClothShape getClothShape(Shape shape) ...
}



🔎 팩토리 메소드 vs 추상 팩토리


팩토리 메소드 패턴

  • 한 팩토리당 한 종류의 객체에 대한 생성
  • 서브클래스에 의존하여 인스턴스 생성

추상 팩토리 패턴

  • 한 팩토리당 연관된 모든 종류의 객체 생성을 추상화

차이점 참고

profile
백엔드를 사랑하는 초보 개발자

0개의 댓글