목차
팩토리 메소드 패턴
팩토리 메소드 패턴(Factory Method Pattern)은 객체 생성을 위한 인터페이스를 제공하지만, 인스턴스화는 서브클래스가 결정하도록 하는 디자인 패턴입니다.
이 패턴은 상속과 다형성을 활용하여, 객체 생성 과정을 클라이언트 코드로부터 분리하고, 객체 생성을 확장할 수 있도록 합니다.
즉, 이전 심플 팩토리와 다른 점은 팩토리 클래스의 인터페이스 혹은 추상 클래스를 구현한다는 점입니다.
심플 팩토리, 팩토리 메소드, 추상 팩토리 패턴 공통정, 차이점
1.
심플 팩토리 패턴 (Simple Factory Pattern)
•
공통점 : 객체 생성을 캡슐화하고, 클라이언트 코드와 생성되는 객체를 분리합니다.
•
차이점 : 이 패턴은 팩토리 클래스 내에서 조건에 따라 인스턴스를 생성합니다. 클라이언트는 팩토리 클래스에 요청을 보내어 필요한 객체를 받습니다. 심플 팩토리는 다형성을 활용하지만 상속이나 인터페이스를 사용하지 않습니다.
2.
팩토리 메소드 패턴 (Factory Method Pattern)
•
공통점 : 객체 생성을 캡슐화하고, 클라이언트 코드와 생성되는 객체를 분리합니다.
•
차이점 : 이 패턴은 추상 클래스 또는 인터페이스를 사용하여 객체 생성을 서브 클래스에 위임합니다. 클라이언트는 추상 인터페이스를 통해 객체를 요청하고, 실제 생성되는 객체의 타입은 서브클래스에서 결정됩니다. 이는 상속을 기반으로 한 확장에 적합합니다.
3.
추상 팩토리 패턴 (Abstract Factory Pattern)
•
공통점 : 객체 생성을 캡슐화하고, 클라이언트 코드와 생성되는 객체를 분리합니다.
•
차이점 : 추상 팩토리 패턴은 여러 종류의 관련있는 또는 의존적인 객체들을 생성하기 위한 인터페이스를 제공합니다. 이 패턴은 서로 다른 팩토리 클래스를 생성하여, 각각 다른 종류의 객체 그룹을 생성할 수 있게 합니다. 이 패턴은 서로 관련 있는 여러 객체들을 일관된 방식으로 생성할 때 유용합니다.
팩토리 메소드 패턴의 장,단점
장점
•
확장성과 유연성 : 새로운 타입의 객체를 추가하려면, 단순히 새로운 서브클래스를 만들고 팩토리 메소드를 오버라이드하면 됩니다. 클라이언트 코드를 변경할 필요가 없습니다.
•
OCP 준수 : 기존 코드를 변경하지 않고도 새로운 기능을 추가할 수 있습니다.
•
단일 책임 원칙(SRP) 준수 : 객체 생성과 사용을 분리하여 각각의 클래스가 단일 책임을 가집니다.
단점
•
클래스 수 증가 : 각각의 새로운 제품을 위해 새로운 서브클래스를 생성해야 하므로, 시스템의 복잡성이 증가할 수 있습니다.
•
구현 복잡성 증가 : 팩토리 메소드 패턴은 구현에 있어서 심플 팩토리 패턴보다 복잡할 수 있습니다.
팩토리 메소드 패턴의 구조
1.
제품 인터페이스(Product Interface) : 생성될 객체들의 공통 인터페이스입니다.
2.
구체적 제품(Concrete Products) : 제품 인터페이스를 구현하는 실제 객체들입니다.
3.
생성자 인터페이스(Creator Interface) : 팩토리 메소드를 정의합니다.
4.
구체적 생성자(Concrete Creators) : 팩토리 메소드를 구현하여 구체적인 제품을 생성합니다.
팩토리 메소드 패턴의 UML
아래는 팩토리 메소드 패턴 UML입니다.
팩토리 메소드 패턴의 구현
팩토리 메소드 패턴의 간단한 구현은 실제 유니티에서 사용할 법한 게임 개발 방식으로 설명하겠습니다.
다른 팩토리 패턴들과의 구현에서 어떤 차이점이 있는지 이 부분에서 확인 바랍니다.
인터페이스 (Interface)
public interface IEnemy {
void Attack();
}
C#
복사
•
역할 : '적'을 나타내는 인터페이스입니다. 팩토리 메소드 패턴에서 모든 '적' 객체는 이 인터페이스를 구현해야 합니다.
•
목적 : 다양한 타입의 '적'들이 공통 인터페이스를 공유함으로써, 클라이언트 코드는 구체적인 '적'의 타입에 대해 알 필요 없이 이 인터페이스를 통해 상호작용할 수 있습니다.
구체적인 제품 클래스 (Concrete Product Classes)
public class Zombie : IEnemy {
public void Attack() {
Debug.Log("Zombie Attack");
}
}
public class Alien : IEnemy {
public void Attack() {
Debug.Log("Alien Attack");
}
}
C#
복사
•
역할 : Zombie와 Alien 클래스는 IEnemy 인터페이스를 구현합니다. 이들은 실제 '적' 객체의 구체적인 형태입니다.
•
목적 : 각 클래스는 '적'의 특정 타입을 나타내며, 자신만의 Attack 메소드를 구현하여 독특한 공격 행동을 정의합니다.
추상 생성자 (Abstract Creator) (추상 팩토리) (Creator)
public abstract class Level {
public abstract IEnemy CreateEnemy();
public void SpawnEnemy() {
var enemy = CreateEnemy();
enemy.Attack();
}
}
C#
복사
•
역할 : Level 클래스는 추상 클래스로, 팩토리 메소드인 CreateEnemy를 정의합니다. 이 메소드는 IEnemy 객체를 생성하는 책임을 가집니다.
•
목적 : 서브클래스에서 CreateEnemy 메소드를 구현하여, 각 레벨에 적합한 '적' 객체를 생성하도록 합니다.
구체적 생성자 (Concrete Creators)
public class EasyLevel : Level {
public override IEnemy CreateEnemy() {
return new Zombie();
}
}
public class HardLevel : Level {
public override IEnemy CreateEnemy() {
return new Alien();
}
}
C#
복사
•
역할 : EasyLevel과 HardLevel 클래스는 Level 클래스를 상속받고, CreateEnemy 메소드를 오버라이드하여 구체적인 '적' 객체를 생성합니다.
•
목적 : 각 레벨 클래스는 해당 레벨의 특성에 맞는 '적' 타입을 생성합니다. 예를 들어, EasyLevel은 Zombie를, HardLevel은 Alien을 생성합니다.
클라이언트 코드 (Client Code) 실제 사용 방법
public class Game {
void StartGame() {
Level level = new EasyLevel();
level.SpawnEnemy();
}
}
C#
복사
•
역할 : Game 클래스는 클라이언트 코드로서, 특정 레벨의 '적' 객체를 필요로 합니다. 이 클래스는 Level의 서브클래스 인스턴스를 만들고, 해당 인스턴스를 통해 '적'을 생성 및 사용합니다.
◦
해당 인스턴스는 팩토리 매니저를 통해 구현할 수도 있습니다.
•
목적 : 클라이언트는 구체적인 객체 생성 과정을 알 필요 없이, 필요한 레벨의 객체를 사용하여 게임 로직을 수행합니다.