4. Factory Pattern

최정훈·2024년 11월 4일

1. Factory Pattern의 필요성


피자 가게를 운영하고 있다고 가정하자. 피자에는 여러가지 종류가 있으므로, 피자 주문이 들어오면 피자의 종류에 따라서 다른 객체를 생성해야 할 것이다. 하지만, 이는 OCP를 위배하는 원칙이다. 그렇다면, 지금 문제가 되는 피자 객체를 생성하는 부분을 캡슐화하면 문제를 해결할 수 있을 것이다.

2. Simple Factory Pattern


public class SimplePizzaFactory{
	public Pizza CreatePizza(string type){
		Pizza pizza = null;
		//피자의 종류에 따라서 피자 인스턴스를 생성
		//.
		//.
		//.
		
		return pizza;
	}
}

이는 피자를 생성하는 부분을 캡슐화하여 별도의 클래스로 구별한 것이다. 이제, 피자 객체를 생성할 일이 있으면, 이 클래스의 CreatePizza() 매서드를 호출하면 되고, 메뉴에 변경이 생기더라도 해당 클래스만 수정하면 된다.

그럼 이제 피자집이 프랜차이즈화 되어서, 분점을 낸다고 가정하자. 분점과 본점에서의 맛의 차이는 최소화되어야 함으로, 피자를 만드는 과정을 획일화하고, 지역의 특색에 따라서 변화를 주어야한다. 이를 위해서는 기존의 클래스를 추상 클래스로 구현해야한다.

public abstract class PizzaStore{
	public Pizze OrderPizza(){
		return pizza;
	}
	
	protected abstract Pizza CreatePizze(string type);
	
}

위와 같이 추상클래스를 정의하고, 각 지역에 따라서 이를 상속받아 서브클래스를 구체화한다.

이와 같이 Factory Pattern을 사용하면, 객체를 생성하는 부분을 한 곳에 몰아넣을 수 있고, 나중에 수정이 필요할 때도, 해당 부분만 수정해도 된다는 장점이 있다. 또한, 예시에서는 추상클래스를 통해서 구현했지만, 인터페이스를 바탕으로 프로그래밍할 수 있어서 유연성과 확장성이 뛰어난 코드를 생성할 수 있다.

3. 객체 의존성, DIP


DIP(의존성 뒤집기 원칙) - 구체적인 클래스에 의존하지 않고, 추상적인 클래스에 의존하게 해야한다.

이는 고수준 구성요소가 저수준 구성요소에 의존하면 안되며, 항상 추상화에 의존하게 만들어야 한다는 의미이다. 앞선 예시에서의 PizzaStore 는 고수준 구성요소이고, 이로부터 생성되는 각종 pizza들은 저수준 구성요소이다. PizzaStore 는 모든 피자 객체를 직접 생성해야 하기 때문에, 모든 pizza 객체에 의존한다고 할 수 있다.

이를 해결하기 위해서는 Pizza 라는 추상클래스를 만들고,PizzaStore 가 이에 의존하게 하여, 피자 객체들을 생성하는 부분을 분리해야한다. 이렇게 하면 고수준, 저수준 구성요소들이 모두 Pizza 에 의존한다는 사실을 알 수 있다.

4. Abstract Factory Pattern


구상 클래스에 의존하지 않고도 서로 연관되거나 의존적인 객체로 이루어진 제품군을 생성하는 인터페이스를 제공한다.

제품군과 인터페이스가 키워드이다. 서로 관련이 있는 객체들을 묶어서 조건에 따라 객체들을 생성하도록, 팩토리 클래스를 만들어서 객체를 생성하는 패턴이다.

피자가게를 예로 들면, 각 피자집에 재료를 전달해야 한다. 하지만, 각 지점마다 원하는 재료들이 다 다르다. Factory Method Pattern을 사용하면, 재료들이 아닌, Pizza자체와 그 내부의 재료들을 함께 묶기 때문에, Abstract Factory Pattern과는 거리가 멀다.

profile
게임개발자(희망)의 공부일지

0개의 댓글