Chapter 4. 심플 팩토리 패턴(Simple Factory Pattern)

Date:     Updated:

카테고리:

태그:

인프런에 있는 이재환님의 강의 게임 디자인 패턴 with Unity 를 듣고 정리한 필기입니다. 😀

Chapter 4. Simple Factory Pattern

🔔 Factory Pattern

  • Factory : 객체 생성을 처리하는 클래스
  • Factory Pattern : 객체를 생성하고자 할 때 사용하는 패턴
    • 종류
      1. Simple Factory Pattern
        • 팩토리 패턴의 가장 기본이 된다.
        • OOP 에서 늘상 사용되기 때문에 패턴이라고 하기도 뭐하지만 팩토리 메서드와 추상 팩토리 패턴의 가장 기본이 되기 때문에 확실히 짚고 넘어가야 한다.
        • 주어진 입력을 기반으로 다른 유형의 객체를 리턴하는 메소드가 있는 팩토리 클래스

      2. Factory Method Pattern
      3. Abstract Factory Pattern

하나의 클래스로 여러가지 타입의 객체(자식)를 찍어내어 리턴하는 함수를 가진 하나의 공장(부모클래스)를 만든다. 다형성

여러개의 자식 오브젝트들을 하나의 함수로 쉽게 한방에 생성하기 위해 사용하는 패턴

  • 객체 생성을 한군데에서만 관리할 수 있따는 장점이 있다.
    • 여러 자식 타입들에게서 중복되는 내용을 제거할 수 있음.


🔔 예제 1

구조

  • 📜Unit 추상 클래스
    • 📜Marine 상속
      • move() 오버라이딩
    • 📜Firebat 상속
      • move() 오버라이딩
    • 📜Medic 상속
      • move() 오버라이딩
  • 📜Factory
    • 📜Unit의 세 자식 타입들을 한번에 찍어내어 리턴해주는 함수 createUnit를 가지고 있다.
    • 팩토리 클래스가 됨
  • 📜FactoryUse.cs
    • 유니티 Start() 함수에서 실제로 📜Factory를 사용하여 createUnit함수를 호출해 3개의 Unit을 찍어낸다.
    • 각 유닛의 move()를 실행시킨다.

📜Unit.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class Unit
{
	public abstract void move ();
}

public class Marine : Unit {

    public Marine()
    {
        Debug.Log("Marine 생성 !!!");
    }

    public override void move ()
	{
		Debug.Log ("Marine 이동 !!!");
	}
}

public class Firebat : Unit {

    public Firebat()
    {
        Debug.Log("Firebat 생성 !!!");
    }

    public override void move ()
	{
		Debug.Log ("Firebat 이동 !!!");
	}
}

public class Medic : Unit {

    public Medic()
    {
        Debug.Log("Medic 생성 !!!");
    }

    public override void move()
    {
        Debug.Log("Medic 이동 !!!");
    }
}

📜Factory.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum UnitType
{
	Marine,
	Firebat,
	Medic
}

public class UnitFactory
{
	public static Unit createUnit(UnitType type)
	{
		Unit unit = null;

		switch (type) {
            case UnitType.Marine:
                unit = new Marine();
                break;
            case UnitType.Firebat:
                unit = new Firebat();
                break;
            case UnitType.Medic:
                unit = new Medic();
                break;
        }
        return unit;
	}
}

부모인 Unit 타입의 unit에 3 개의 자식 타입들을 참조하여 unit을 리턴하는 static 함수다. 즉, 인수로 들어온 유닛을 생성하고 리턴해주는 공장과도 같은 역할을 한다.

📜FactoryUse.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FactoryUse : MonoBehaviour {

	void Start () {

		Unit unit1 = UnitFactory.createUnit(UnitType.Marine);
        Unit unit2 = UnitFactory.createUnit(UnitType.Firebat);
        Unit unit3 = UnitFactory.createUnit(UnitType.Medic);

        unit1.move();
        unit2.move();
        unit3.move();
    }
}
  • static 함수이므로 클래스 이름으로 바로 접근
    • UnitFactory.createUnit(UnitType.Marine)
  • 부모 타입으로 자식을 참조
    • Unit unit2 = UnitFactory.createUnit(UnitType.Firebat)
  • createUnit으로부터 리턴받은 자식 객체로 move()를 호출한다.
    • move() 함수는 추상 함수이므로 자식들이 반드시 오버라이딩 해야 하며 부모인 Unit 타입으로 자식 객체를 참조해도 자식이 오버라이딩한 move()가 호출된다.
    • 각각 메딕, 파이어뱃, 마린의 move()가 호출됨
      unit1.move();
      unit2.move();
      unit3.move();
      


🔔 예제 2

Unit을 상속 받는 FirebatMarine 프리팹을 팩토리 패턴을 사용하여 게임 도중에 실시간으로 생성해보자.

구조

  • 📜Unit 추상 클래스
    • 📜Marine 상속
      • move() 오버라이딩
    • 📜Firebat 상속
      • move() 오버라이딩
  • 📜Factory
    • 📜Unit의 세 자식 타입들을 한번에 찍어내어 리턴해주는 static 함수 createUnit를 가지고 있다.
    • 팩토리 클래스가 됨
  • 📜FactoryUse.cs
    • 유니티 Start() 함수에서 실제로 📜Factory를 사용하여 createUnit함수를 호출해 3개의 Unit을 찍어낸다.
    • 각 유닛의 move()를 실행시킨다.

📜Unit.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class Unit : MonoBehaviour
{
	public abstract void Move ();
}

📜Marine.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Marine : Unit {

    void Start()
    {
        Debug.Log("Marine 생성 !!!");
    }

    public override void Move()
    {
        Debug.Log("Marine 이동 !!!");
    }
}

📜Firebat.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Firebat : Unit {

    void Start()
    {
        Debug.Log("Firebat 생성 !!!");
    }

    public override void Move()
    {
        Debug.Log("Firebat 이동 !!!");
    }
}

📜Factory.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum UnitType
{
	Marine,
	Firebat
}

public class Factory : MonoBehaviour
{
    public GameObject marine = null;
    public GameObject firebat = null;

    public GameObject createUnit(UnitType type)
	{
        //Unit unit = null;
        GameObject unit = null;

        float x = (float)Random.Range(0, 6);
        float z = (float)Random.Range(0, 6);

        switch (type) {
            case UnitType.Marine:
                //unit = new Marine();
                unit = Instantiate(marine, new Vector3(x, 1.0f, z), Quaternion.identity);
                break;
            case UnitType.Firebat:
                //unit = new Firebat();
                unit = Instantiate(firebat, new Vector3(x, 0.5f, z), Quaternion.identity);
                break;
        }

        return unit;
	}
}

  • marine, firebat에 각각 프리팹을 연결해준다.
  • 부모인 Unit 타입의 unit에 자식들 타입들을 참조하여 unit을 리턴하는 함수다. 즉, 인수로 들어온 유닛을 생성하고 리턴해주는 공장과도 같은 역할을 한다.
    • 각 자식들의 프리팹을 x,z 랜덤한 위치에 Instantiate 하고
    • 이를 리턴한다.

📜FactoryUse.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FactoryUse : MonoBehaviour {

    Factory factory = null;
    GameObject unit1 = null;
    GameObject unit2 = null;
    GameObject unit3 = null;

    void Start () {
        factory = GetComponent<Factory>();

        unit1 = factory.createUnit(UnitType.Marine);
        unit2 = factory.createUnit(UnitType.Firebat);
        unit3 = factory.createUnit(UnitType.Firebat);

        StartCoroutine("UnitAction");
    }

    IEnumerator UnitAction()
    {
        yield return new WaitForSeconds(0.2f);

        // 추상클래스 Unit을 이용하여 Marine, Firebat의 구분없이
        // 접근하여 사용할 수 있다.
        unit1.GetComponent<Unit>().Move();
        unit2.GetComponent<Unit>().Move();
    }
}
  • 부모 타입으로 자식을 참조
    • Unit unit2 = UnitFactory.createUnit(UnitType.Firebat)
  • createUnit으로부터 리턴받은 자식 객체로 move()를 호출한다.
    • move() 함수는 추상 함수이므로 자식들이 반드시 오버라이딩 해야 하며 부모인 Unit 타입으로 자식 객체를 참조해도 자식이 오버라이딩한 move()가 호출된다.
    • 각각 파이어뱃, 마린의 move()가 호출됨


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Design Pattern 카테고리 내 다른 글 보러가기

댓글 남기기