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

Date:     Updated:

Categories:

Tags:

인프런에 있는 이재환님의 강의 게임 디자인 패턴 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을 상속 받는 Firebat과 Marine 프리팹을 팩토리 패턴을 사용하여 게임 도중에 실시간으로 생성해보자.

구조

  • 📜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 카테고리 내 다른 글 보러가기

Leave a comment