(C#)디자인패턴 - 팩토리 패턴

티원·2025년 9월 29일

디자인패턴

목록 보기
1/16

팩토리 패턴

객체 생성을 서브클래스 (다른클래스)에 위임하여 확장 가능
객체 생성 코드를 단순화, 설계도를 숨겨서 접근을 어렵게
용도: 적 스폰 시스템, 아이템 생성, 탄환 발사 등등

팩토리 패턴을 쓰는 이유?

책임 분리, 코드 확장성, 결합도를 낮춤, 가독성 ,여러 객체를 만들때(유지보수)

팩토리 패턴을 쓰지않는다면 객체를 생성하는 코드를 수정할때 특정 생성코드와 new의 코드까지 바뀐다면 new까지 수정해줘야함.
생성하는 로직이 팩토리 한곳에 모여있으면 어떤 것을 생성하고 있는지 한눈에 보기쉽다.

부모1개에 자식이 4개 이상.. 이런 것일때 쓰면 좋을듯

1. 팩토리 패턴을 안쓴다면?

게임에 무기가 3개있다고 가정

Weapon w1 = new Sword();
Weapon w2 = new Gun();
Weapon w3 = new Bow();

그런데 이게 타입별로 생성되는 무기가 달라야한다면? (메인문이 상당히 길어짐)

string weaponType = "Sword"; //enum으로 해야하지만 string으로 한다치면
Weapon weapon;

if (weaponType == "Sword")
    weapon = new Sword();
else if (weaponType == "Gun")
    weapon = new Gun();
else if (weaponType == "Bow")
    weapon = new Bow();

2. 팩토리 패턴사용

아래처럼 해놓고 생성을 팩토리에서 담당하면 된다

WeaponFactory factory = new WeaponFactory();
Weapon weapon = factory.Create(weaponType);

팩토리 패턴의 종류

  • 단순 팩토리 패턴
  • 팩토리 메서드 패턴 (Factory Method)

단순 팩토리 패턴

하나의 팩토리 클래스 안에서 조건부 로직을 통해 다양한 객체를 생성

팁: 아래 코드에서 ShipFactory 안에 BattleShipCargoShip 클래스가 있는데 이걸 외부로 빼놓아도 됨. 지금은 외부에서 BattleShip의 객체를 생성하지 못하게 하려고 넣음

코드

public enum eShipType
{
    BattleShip, CargoShip
}
public abstract class Ship
{
    public abstract void Sail();
}
public class ShipFactory
{
    public class BattleShip : Ship  //public으로 하는게 좋다고함. 외부에서 쓸수도있으니까
    {
        public override void Sail()
        {
            Console.WriteLine("BattleShip항해 시작");
        }
    }
    public class CargoShip : Ship
    {
        public override void Sail()
        {
            Console.WriteLine("CargoShip항해 시작");
        }
    }
    public Ship CreateShip(eShipType shipType, int x )
    {
        Ship ship = null;

        switch(shipType)
        {
            case eShipType.BattleShip:
                ship = new BattleShip();
                break;
            case eShipType.CargoShip:
                ship = new CargoShip();
                break;
            default:
                Console.WriteLine("예외처리. 코드수정필요");
                break;
        }
        return ship;
    }
}

static void Main(string[] args)
{
    ShipFactory factory = new ShipFactory();
    Ship ship =  factory.CreateShip(eShipType.BattleShip, 1);
    ship?.Sail(); // BattleShip항해 시작
    //BattleShip ship = new BattleShip(); //불가능, 외부에서 접근 불가능하게 ShipFactory 클래스에 있음
    ShipFactory.BattleShip ship1 = new ShipFactory.BattleShip(); //굳이 만들어야한다면 이렇게
}

팩토리 메서드 패턴

상위 클래스에서 팩토리 메서드를 선언하고, 객체 생성은 하위 클래스가 자신만의 팩토리 메서드를 구현하여 결정하도록 위임

코드

public abstract class Ship
{
    public abstract void Sail();
}
public class BattleShip : Ship  //public으로 하는게 좋다고함. 외부에서 쓸수도있으니까
{
    public override void Sail()
    {
        Console.WriteLine("BattleShip항해 시작");
    }
}
public class CargoShip : Ship
{
    public override void Sail()
    {
        Console.WriteLine("CargoShip항해 시작");
    }
}
public abstract class ShipFactory
{
    public abstract Ship CreateShip();
}
public class BattleShipFactory : ShipFactory
{
    public override Ship CreateShip()
    {
        return new BattleShip();
    }
}
public class CargoShipFactory : ShipFactory
{
    public override Ship CreateShip()
    {
        return new CargoShip();
    }
}

static void Main(string[] args)
{
    ShipFactory factory1 = new BattleShipFactory();
    Ship myShip1 = factory1.CreateShip();
    myShip1.Sail(); //BattleShip항해 시작
    ShipFactory factory2 = new CargoShipFactory();
    Ship myShip2 = factory2.CreateShip();
    myShip2.Sail(); //CargoShip항해 시작
}

0개의 댓글