-
추상 팩토리 패턴 (Abstract Factory Pattern)Design Pattern/Creational Patterns 2020. 1. 28. 02:35
추상 팩토리 패턴(Abstract Factory Pattern)은 다양한 구성요소에서 특정 목적에 따라 호환성을 갖는 객체들을 생성해야할 때 유용하게 사용할 수 있습니다.
이 팩토리를 사용함으로써 개발자는 각 객체의 생성에 있어서, 사용 목적에 어떤 객체들이 부합하는지 확인하고 검증해야 하는 비용이 사라지게 됩니다. 이를 통해 편의성을 얻고, 유지보수의 비용을 줄일 수 있습니다.
예를 들어, 스타크래프트에서 게임을 시작하자마자의 상황을 가정하겠습니다.
처음에 세팅되어있어야 하는 건물과 일꾼은 사용자의 종족 선택에 따라 다를 것입니다.
테란을 선택했다면 커맨드 센터와 SCV 4기가 있어야하며, 저그의 해처리가 있거나, 프로토스의 프로브들이 있으면 안됩니다.
이러한 상황에서, 종족에 따라 어떤 건물이, 어떤 일꾼이 호환성을 갖는지 확인해야 하는 비용을 팩토리 클래스를 사용함으로써 없앨 수 있습니다.
아주 간단하게 모델링하여 구현을 해보도록 하겠습니다.
1. InitializationFactory
호환성 있는 Worker와 Building 클래스의 객체를 생성할 수 있도록 하는 추상 클래스입니다.
이 클래스를 상속받아 각 종족에 대한 팩토리를 구현합니다.
2. Worker
Worekr는 자원을 모을 수 있고, 건물을 지을 수 있는 인터페이스를 구현하도록 모델링합니다.
3. Building
여기서 Building 클래스는 아주 간단히 모델링하여 각 종족에 호환되는 유닛을 생성하는 인터페이스를 구현하도록 합니다.
4. Game
각 팩토리를 사용하여 게임의 초기 상태를 세팅하고, 건물과 유닛 객체를 사용하는 클래스입니다.
이렇게 모델링한 것을 클래스 다이어그램으로 나타내면 아래와 같습니다.
Class Diagram 실제 구현을 해보도록 하겠습니다.
1. Interface 정의
public interface Buildable { public void build(); }
public interface Gatherable { public void gather(); }
public interface Creatable { public void createWorker(); }
2. Worker 클래스와 하위 SCV, 드론 클래스
위에서 정의한 Gatherable과 Buildable 인터페이스를 하위 클래스에서 구현하도록 정의합니다.
public abstract class Worker implements Gatherable, Buildable { }
그리고 SCV,와 드론이 자원을 수집하고, 건물을 짓는 부분은 각각 종족에 맞게 모델링하여 메소드를 정희하도록 합니다.
public class TerranScv extends Worker { @Override public void gather() { System.out.println("미네랄을 절단하다"); } @Override public void build() { System.out.println("건물을 짓다"); } }
public class ZergDrone extends Worker { @Override public void gather() { System.out.println("침을 뱉다"); } @Override public void build() { System.out.println("건물용 번데기로 변한다"); } }
3. Building 클래스와 하위 클래스
건물은 유닛을 생성할 수 있도록 모델링하여 하위 클래스에서 유닛을 생성할 수 있도록 합니다.
public abstract class Building implements Creatable { }
public class TerranCommandCenter extends Building { @Override public void createWorker() { System.out.println("scv를 생성한다"); } }
public class ZergHatchery extends Building { @Override public void createWorker() { System.out.println("드론을 생성한다"); } }
4. InitializationFactory 클래스와 하위 클래스
각 종족에 따라 호환성을 갖는 객체를 생성하도록 도와주는 팩토리 추상 클래스를 만듭니다.
그리고 하위 클래스에서 호환성을 갖도록 메소드를 구현합니다.
import java.util.List; public abstract class InitializationFactory { abstract public Building createBuilding(); abstract public List<Worker> createUnit(); }
import java.util.ArrayList; import java.util.List; public class InitializationFactoryTerran extends InitializationFactory { @Override public Building createBuilding() { return new TerranCommandCenter(); } @Override public List<Worker> createUnit() { int hp = 60; int power = 5; List<Worker> scvList = new ArrayList<>(); for (int i = 0; i < 4; ++i) { scvList.add(new TerranScv(power, hp)); } return scvList; } }
import java.util.ArrayList; import java.util.List; public class InitializationFactoryZerg extends InitializationFactory { @Override public Building createBuilding() { return new ZergHatchery(); } @Override public List<Worker> createUnit() { int power = 4; int hp = 50; List<Worker> droneList = new ArrayList<>(); for (int i = 0; i < 4; ++i) { droneList.add(new ZergDrone(power, hp)); } return droneList; } }
5. Game 클래스
마지막으로 종족을 선택하고 게임을 시작했다고 가정했을 때, 초기 화면에 각 종족에 맞는 건물과 4개의 유닛을 생성하여 게임을 하는 사람에게 보여준다고 가정한 메인문을 작성합니다.
import java.util.List; public class Game { public static void main(String[] args) { InitializationFactory[] initFactory = {new InitializationFactoryTerran(), new InitializationFactoryZerg()}; for (InitializationFactory factory : initFactory) { Building building = factory.createBuilding(); List<Worker> workers = factory.createUnit(); workers.get(0).gather(); workers.get(1).build(); building.createWorker(); System.out.println("================"); } } } /* 실행 화면 미네랄을 절단하다 건물을 짓다 scv를 생성한다 ================ 침을 뱉다 건물용 번데기로 변한다 드론을 생성한다 ================ */
이렇게 사용하게 되면, 유닛과 건물의 종족을 사용자가 확인하여 객체를 생성하지 않아도 팩토리에서 호환성 있게 객체를 생성하게 됩니다.
우리는 객체가 올바르게 생성되었는지 신경쓰지 않고, 같은 방식으로 사용할 수 있습니다.
상황에 따라 객체를 생성하는 부분에 적용하여 유용하게 적용할 수 있을 것이라고 판단됩니다.
'Design Pattern > Creational Patterns' 카테고리의 다른 글
싱글톤 패턴 (Singleton Pattern) (0) 2020.02.04