이 글은 해당 유튜브를 보고 진행한 것에 대해 공부한 것을 정리한 글입니다.
팩토리 패턴 (Factory Pattern)

객체 생성을 위한 설계 패턴
팩토리 패턴은 객체 생성을 전담하는 별도의 클래스를 두고,
객체를 생성하는 로직을 클라이언트 코드로부터 분리하는 디자인 배턴입니다.
주요 특징
- 객체 생성에 대한 인터페이스와 구현의 분리
- 클라이언트는 어떤 클래스의 인스턴스가 생성되는지 몰라도 되고, 단순히 인터페이스만 알면 됩니다.
- 객체 생성과 관련된 세부사항을 캡슐화
- 조건 분기, 설정 값, 초기화 등 복잡한 생성 과정을 은닉화합니다.
- 유연한 확장성
- 새로운 객체를 생성하는 방식에 대한 유연한 확장이 가능합니다.
- 새로운 타입이 추가되어도 기존 코드를 변경할 필요 없이 팩토리 내부 및 새로 추가될 타입만 수정하면 됩니다.
장점
- 단일 책임 원칙(SRP) 준수
- 객체 생성 책임을 분리하여 클래스 책임이 명확해집니다.
- 개방/폐쇄 원칙(OCP) 준수
- 새로운 객체 타입을 추가할 때 기존 코드를 수정하지 않아도 됩니다.
- 코드 재사용 및 유지보수 용이
- 클라이언트와 구체 객체 간 결합도 감소
- 생성 로직을 외부로 위임하므로 결합도가 낮아집니다.
단점
- 클래수 수 증가
- 팩토리, 생성자, 인터페이스 등 구조가 복잡해질 수 있습니다.
- 다수의 클래스와 서브 클래스를 만들게되므로써, 오버헤드가 발생할 수 있습니다.
개선 방안
딕셔너리 기반 탐색 방식 적용
Dictionary<string, IUnit> unitMap = new()
{
{ "Archer", new Archer() },
{ "Knight", new Knight() },
{ "Wizard", new Wizard() }
};
return unitMap[unitId];
- 제품을 키 - 값 페어로 딕셔너리에 저장합니다.
- 주로 고유한 문자열 식별자(이름 또는 ID 등)를 키로 사용하고, 유형을 값으로 사용합니다.
- 제품 또는 제품의 공장을 더 편리하게 검색할 수 있습니다.
Static화 혹은 Singleton 적용
public static class SkillFactory
{
public static ISkill Create(string skillId)
{
// ...
}
}
- 팩토리 클래스를 static 또는 singleton으로 만들어 글로벌하게 공유합니다.
- 매번 팩토리를 생성할 필요 없이 객체 생성을 효율적으로 관리합니다.
Object pool Pattern과 병행
public class BulletFactory
{
public Bullet CreateBullet()
{
return BulletPool.GetAvailableBullet();
}
}
- 팩토리는 객체를 생성하는 책임이 있지만, 반드시 새로운 오브젝트를 인스턴스화하거나 만들어야 하는 것은 아닙니다.
- 계층 구조에 있는 기존의 오브젝트를 검색할 수도 있습니다.
- 많은 오브젝트를 한 번에 인스턴스화하는 경우 풀링을 병행해 성능을 향상할 수 있습니다.
- 팩토리 내부에서 오브젝트 풀을 참조하면, 재사용 가능한 객체를 제공할 수 있습니다.
Factory Method(팩토리 메서드) vs Abstract Factory(추상 팩토리)
Factory Method 패턴
정의
Factory Method 패턴은 객체 생성을 서브클래스에 위임하는 방식입니다.
객체를 생성하는 메서드 자체는 추상화되어 있고, 하위 클래스가 이 메서드를 오버라이드하여 실제 객체를 생성합니다.
핵심 개념
- 상속 기반의 객체 생성 구조
- 단일 객체를 생성
- 구체 클래스가 아닌 인터페이스/추상 클래스만 사용하여 클라이언트 코드와의 결합도를 낮춤
클래스 구조 예시 (C#)
// 제품 인터페이스
public interface IButton
{
void Render();
}
// 구체 제품
public class WindowsButton : IButton
{
public void Render() => Console.WriteLine("Windows Button");
}
public class MacOSButton : IButton
{
public void Render() => Console.WriteLine("MacOS Button");
}
// 팩토리 클래스
public abstract class Dialog
{
public abstract IButton CreateButton();
public void RenderWindow()
{
IButton button = CreateButton();
button.Render();
}
}
// 구체 팩토리
public class WindowsDialog : Dialog
{
public override IButton CreateButton() => new WindowsButton();
}
public class MacOSDialog : Dialog
{
public override IButton CreateButton() => new MacOSButton();
}
Abstract Factory 패턴
정의
Abstract Factory 패턴은 관련된 객체의 집합(제품군)을 생성하는 인터페이스를 제공합니다.
클라이언트는 제품의 구체적인 클래스를 몰라도, 팩토리 인터페이스만으로 일관된 제품군을 생성할 수 있습니다.
핵심 개념
- 제품군 생성에 초점 (서로 관련된 여러 객체들을 함께 생성)
- 구체 클래스의 사용 없이 전체 제품군을 추상화
- 팩토리 메서드를 묶은 팩토리 클래스
클래스 구조 예시 (C#)
// 제품 인터페이스
public interface IButton
{
void Render();
}
public interface ITextBox
{
void Write();
}
// 구체 제품군 1
public class WindowsButton : IButton
{
public void Render() => Console.WriteLine("Windows Button");
}
public class WindowsTextBox : ITextBox
{
public void Write() => Console.WriteLine("Windows TextBox");
}
// 구체 제품군 2
public class MacOSButton : IButton
{
public void Render() => Console.WriteLine("MacOS Button");
}
public class MacOSTextBox : ITextBox
{
public void Write() => Console.WriteLine("MacOS TextBox");
}
// 추상 팩토리
public interface IGUIFactory
{
IButton CreateButton();
ITextBox CreateTextBox();
}
// 구체 팩토리
public class WindowsGUIFactory : IGUIFactory
{
public IButton CreateButton() => new WindowsButton();
public ITextBox CreateTextBox() => new WindowsTextBox();
}
public class MacOSGUIFactory : IGUIFactory
{
public IButton CreateButton() => new MacOSButton();
public ITextBox CreateTextBox() => new MacOSTextBox();
}
구현 예시

IProduct 인터페이스
public interface IProduct
{
public string ProductName { get; set; }
public void Initialize();
}
public abstract class Factory : MonoBehaviour
{
public abstract IProduct GetProduct(Vector3 position);
// 모든 공장이 공유하는 메서드
// …
}
IProduct는 생성되는 제품의 공통된 인터페이스입니다.
- ProductName 속성
- 제품 이름을 외부에서 설정하거나 읽기 위한 속성입니다.
- Initialize( ) 메서드
- 각 제품에 필요한 초기화 로직을 담기 위한 메서드입니다.
Factory 추상 클래스
public class ConcreteFactoryA : Factory
{
[SerializeField]
private ProductA productPrefab;
public override IProduct GetProduct(Vector3 position)
{
// 프리팹 인스턴스를 생성하고 제품 컴포넌트 가져오기
GameObject instance
= Instantiate(productPrefab.gameObject, position, Quaternion.identity);
ProductA newProduct = instance.GetComponent<ProductA>();
// 각 제품에 자체 로직 포함
newProduct.Initialize();
return newProduct;
}
}
Factory는 추상 클래스이며, 팩토리의 기본 템플릿을 정의합니다.
- GetProduct(position) 메서드
- 제품을 생성할 위치를 받아 제품을 반환합니다.
- abstract 키워드
- 이 메서드는 abstract 키워드로 정의되어 있기 때문에, 상속받는 클래스에서 반드시 구현해야 합니다.
IProduct 구현부를 가지는 ProductA 클래스
public class ProductA : MonoBehaviour, IProduct
{
[SerializeField]
private string productName = "ProductA";
public string ProductName { get => productName; set => productName = value ; }
private ParticleSystem particleSystem;
public void Initialize()
{
// 이 제품에 대한 모든 고유 로직
gameObject.name = productName;
particleSystem = GetComponentInChildren<ParticleSystem>();
particleSystem?.Stop();
particleSystem?.Play();
}
}
ProductA는 IProduct를 구현한 실제 제품 클래스입니다.
게임 내에서 시각적 / 기능적 효과가 포함된 제품의 실제 구현체입니다.
- ProductName
- 제품의 이름을 관리합니다.
- Initialize( )
- 생성된 오브젝트의 초기 상태를 설정합니다.
Factory 추상클래스를 상속받는 ConcreteFactoryA 클래스
public class ConcreteFactoryA : Factory
{
[SerializeField]
private ProductA productPrefab;
public override IProduct GetProduct(Vector3 position)
{
// 프리팹 인스턴스를 생성하고 제품 컴포넌트 가져오기
GameObject instance
= Instantiate(productPrefab.gameObject, position, Quaternion.identity);
ProductA newProduct = instance.GetComponent<ProductA>();
// 각 제품에 자체 로직 포함
newProduct.Initialize();
return newProduct;
}
}
ConcreteFactoryA는 Factory 추상 클래스를 구현한 구체적인 팩토리 클래스입니다.
프리팹 기반 제품 생성 로직을 구체 팩토리에서 캡슐화한 구조입니다.
- ProductPrefab
- 유니티 인스펙터에서 할당되는 생성한 제품의 프리팹입니다.
- GetProduct( )의 수행
- productPrefab을 지정한 위치에 인스턴스화합니다.
- 인스턴스에서 ProductA 컴포넌트를 가져옵니다.
- 제품 고유 로직을 포함한 Initialize( ) 메서드를 호출합니다.
- 최종적으로 생성된 제품을 IProduct 인터페이스로 반환합니다.
팩토리 패턴 예시
마우스로 씬을 클릭하면 녹색 또는 붉은색 공(객체)가 생기는 쌤플 씬입니다.

public class ClickToCreate : MonoBehaviour
{
[SerializeField] private LayerMask layerToClick;
[SerializeField] private Vector3 offset;
[SerializeField] Factory[] factories;
private Factory factory;
private void Update()
{
GetProductAtClick();
}
private void GetProductAtClick()
{
// check click with raycast
if (Input.GetMouseButtonDown(0))
{
// choose a random factory
factory = factories[Random.Range(0, factories.Length)];
// instantiate product at raycast intersection
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo, Mathf.Infinity, layerToClick)
&& factory != nu1l)
{
factory.GetProduct(hitInfo.point + offset);
}
}
}
}
'Unity' 카테고리의 다른 글
| [Unity] 디자인 패턴 : Singleton 패턴 (0) | 2025.06.17 |
|---|---|
| [Unity] 디자인패턴 : Object Pool (1) | 2025.06.16 |
| [Unity] 디자인 패턴 : Command 패턴 (0) | 2025.06.13 |
| [Unity] 디자인 패턴 : Observer 패턴 (2) | 2025.06.13 |
| [Unity] 디자인 패턴 : State 패턴 (0) | 2025.06.10 |