관련 영상
추상 팩토리
위키피디아
추상 팩토리 패턴
- 관련 객체들의 구상 클래스들을 지정하지 않고도 관련 객체들의 모음을 생성할 수 있도록 하는 생성패턴
- 다양한 구성 요소 별로 '객체의 집합'을 생성해야 할 때 유용하다. 이 패턴을 사용하여 상황에 알맞은 객체를 생성할 수 있다.
추상 팩토리의 구조
- 추상 제품들(Abstract Products)
- 제품 패밀리를 구성하는 개별 연관 제품들의 집합에 대한 인터페이스들을 선언
- 구상 재품들(Concrete Products)
- 변형들로 그룹화된 추상 제품들의 다양한 구현들
- 각 추상 제품은 주어진 모든 변형에 구현되어야 함
- 추상 팩토리(Abstract Factory)
- 각각의 추상 제품들을 생성하기 위한 여러 메서드들의 집합을 선언
- 구상 팩토리(Concrete Factory)
- 추상 팩토리의 생성 메서드들 구현
- 각 구상 팩토리는 제품들의 특정 변형들에 해당하며 해당 특정 변형들만 생성함
- 구상 팩토리들은 구상 제품들을 인스턴스화하거나, 그 제품들의 생성 메서드들의 시그지처들은 그에 해당하는 추상 제품들을 반환해야 함. 그래야 팩토리를 사용하는 클라이언트 코드가 팩토리에서 받은 제품의 특정 변형과 결합되지 않음
- 클라이언트는 추상 인터페이스를 통해 팩토리/제품 변형의 객체들과 소통하는 한 그 어떤 구상 팩토리/제품 변형과 작업할 수 있음. 그래야 팩토리를 사용하는 클라이언트 코드가 팩토리에서 받은 제품의 특정 변형과 결합되지 않음
- 클라이언트는 추상 인터페이스를 통해 팩토리/제품 변형의 객체들과 소통하는 한 그 어떤 구상 팩토리/제품 변형과 작업할 수 있음
추상 팩토리의 적용
- 관련된 제품군의 다양한 패밀리들과 작동해야 하지만, 해당 제품들의 구상 클래스들에 의존하고 싶지 않을 때
- 이러한 클래스들은 미리 알려지지 않았을 수 있으며, 그 때문에 향후 확장성을 허용하기를 원할 수 있다.
- 코드에 클래스가 있고 이 클래스의 팩토리 메서드들의 집합의 기본 책임이 뚜렷하지 않을 때
- 잘 설계된 프로그램에서는 각 클래스는 하나의 책임만 가진다. 클래스가 여러 제품 유형을 상대할 경우, 클래스의 팩토리 메서드들을 독립실행형 팩토리 클래스 또는 완전한 추상 팩토리 구현으로 구현할 가치가 있다.
다른 패턴과의 관계
- 많은 디자인은 복잡성이 낮고 자식 클래스들을 통해 더 많은 커스터마이징이 가능한 팩토리 메서드로 시작해 더 유연하면서도 더 복잡한 추상 팩토리, 프로토타입 또는 빌더 패턴으로 발전해 나간다.
- 빌더는 복잡한 객체들을 단계별로 생성하는 데 중점을 둔다. 추상 팩토리는 관련된 객체들의 패밀리들을 생성하는 데 중점을 둔다. 추상 팩토리는 제품을 즉시 반환하지만 빌더는 제품을 가져오기 전에 당신이 몇 가지 추가 생성 단계들을 실행할 수 있도록 한다.
- 추상 팩토리 클래스들은 팩토리 메서드들의 집합을 기반으로 하는 경우가 많다. 그러나 프로토타입을 사용하여 추상 팩토리의 구상 클래스들의 생성 메서드들을 구현할 수도 있다.
- 추상 팩토리는 하위시스템 객체들이 클라이언트 코드에서 생성되는 방식만 숨기고 싶을 때 퍼사드 대신 사용할 수 있다.
- 추상 팩토리를 브리지와 함께 사용할 수 있다. 이 조합은 브리지에 의해 정의된 어떤 추상화들이 특정 구현들과만 작동할 수 있을 때 유용하다. 이런 경우에 추상 팩토리는 이러한 관계들을 캡슐화하고 클라이언트 코드에서부터 복잡성을 숨길 수 있다.
- 추상 팩토리들, 빌더들 및 프로토타입들은 모두 싱글턴으로 구현할 수 있다.
추상 팩토리로 구현한 테란 유닛 생성과 확장
public abstract class UnitBuilding : MonoBehaviour
{
public abstract void produce();
}
public abstract class RaceCapacity : MonoBehaviour
{
public abstract void expand();
}
- 콘크리트 제품들
- 생성할 유닛과 확장할 인구 대상이 상세하게 구현된 클래스
public class Barracks : UnitBuilding {
public override void produce()
{
Debug.Log("Terran Unit 생산 !!!");
}
}
public class Gateway : UnitBuilding {
public override void produce()
{
Debug.Log("Protoss Unit 생산 !!!");
}
}
public class SupplyDepot : RaceCapacity {
public override void expand()
{
Debug.Log("Terran Capacity +8 !!!");
}
}
public class Pylon : RaceCapacity {
public override void expand()
{
Debug.Log("Protoss Capacity +8 !!!");
}
}
public enum Race
{
Terran,
Protoss,
Zerg
}
public abstract class RaceFactory : MonoBehaviour
{
public abstract GameObject makeCapacityBuilding();
public abstract GameObject makeUnitBuilding();
}
- 콘크리트 팩토리
- 실제로 제품들을 출하하는 로직을 구현한 클래스
public class TerranFactory : RaceFactory
{
public GameObject supply;
public GameObject barracks;
public override GameObject makeCapacityBuilding()
{
//return new SupplyDepot();
return Instantiate(supply, new Vector3(-1.0f, 1.0f, 0.0f), Quaternion.identity);
}
public override GameObject makeUnitBuilding()
{
//return new Barracks();
return Instantiate(barracks, new Vector3(1.0f, 0.5f, 0.0f), Quaternion.identity);
}
}
public class ProtossFactory : RaceFactory
{
public GameObject pylon;
public GameObject gateway;
public override GameObject makeCapacityBuilding()
{
//return new Pylon();
return Instantiate(pylon, new Vector3(-1.0f, 1.0f, 0.0f), Quaternion.identity);
}
public override GameObject makeUnitBuilding()
{
//return new Gateway();
return Instantiate(gateway, new Vector3(1.0f, 0.5f, 0.0f), Quaternion.identity);
}
}
- 이들을 한데 통합하여 클라이언트에 선언해줄 최종 팩토리
public class FactoryMethod : MonoBehaviour {
public Race type = Race.Terran;
public RaceFactory getFactory()
{
RaceFactory factory = null;
switch (type)
{
case Race.Terran:
//factory = new TerranFactory ();
factory = GetComponent<TerranFactory>();
break;
case Race.Protoss:
//factory = new ProtossFactory();
factory = GetComponent<ProtossFactory>();
break;
}
return factory;
}
}
public class FactoryMethodUse : MonoBehaviour {
RaceFactory factory = null;
void Start () {
factory = GetComponent<FactoryMethod>().getFactory();
GameObject capacity = factory.makeCapacityBuilding();
GameObject building = factory.makeUnitBuilding();
capacity.GetComponent<RaceCapacity>().expand();
building.GetComponent<UnitBuilding>().produce();
}
}
추상 팩토리로 구현한 자동차 공장
Github 링크
많은 도움이 되었습니다. 감사해요