C 언어에서 추상적인 공장 설계 모드를 사용하는 방법#

게시물How to use the Abstract Factory design pattern in C#이 먼저 Gary Woodfine에 올라왔다.
추상적인 공장 모델은 Factory Method Design Pattern보다 추상적인 등급이 높다.추상적인 공장 모델을 사용하여 하나의 프레임워크를 정의했다. 이 프레임워크는 일반적인 모델을 따르는 대상을 생성하고 운행할 때 이 공장은 그 어떠한 구체적인 공장과 조합하여 정의된 모델을 따르는 대상을 생성한다.
추상적인 공장 모델은 창조적인 4인방(GoF) 디자인 모델로 그들의 창의적인 저서 Design Patterns: Elements of Reusable Object-Oriented Software에서 정의했다. 그 중에서 그들은 흔히 볼 수 있는 디자인 문제에 일련의 간단하고 간결한 해결 방안을 제공했다.

추상적인 공장 모델은 무엇입니까


몇 개의 관련 대상 클래스를 되돌려 주고 싶을 때, 추상적인 공장 모드를 사용할 수 있으며, 각 클래스는 요청에 따라 몇 개의 다른 대상을 되돌려 줄 수 있습니다.일반적으로 추상적인 공장 모델과 Simple Factory PatternFactory Method Pattern 등 다른 공장 모델을 결합하여 사용할 수 있습니다.
추상적인 공장 모델을 사고하는 가장 좋은 방법은 슈퍼 공장이나 공장의 공장이다.일반적으로 이것은 관련 대상을 만드는 공장을 책임지고 파생 클래스를 명시적으로 지정하지 않는 인터페이스이다.

추상적인 공장 모델의 핵심 구성 요소는 다음과 같다.
추상 공장: 추상 대상을 만드는 추상 용기.
구체적인 공장: 추상적인 용기를 실현하여 구체적인 대상을 만든다.
추상적 대상: 만들 대상의 속성으로 정의된 인터페이스입니다.
구체적인 대상: 관련 추상적인 대상을 인용하여 얻은 실제 대상.
클라이언트: 공장을 사용하여 관련 대상족의 클라이언트 응용 프로그램을 만듭니다.

C의 추상적인 공장 예


우리의 예시에서 우리는 우리의 예시 게임 응용 프로그램을 계속 사용할 것이다. 이 응용 프로그램은 우리의 방법에 전달된 한 그룹의 사용자 수요에 따라 차량을 구축할 것이다.이것은 우리가 Factory Method Design Pattern 글에서 만들기 시작한 가설 게임이다.우리는 이 응용 프로그램을 재구성하여 추상적인 공장 설계 모델을 도입하고 사용자에게 추가 선택을 제공할 것이다.
사용자는 바퀴의 수량, 엔진이 있는지, 화물을 적재할 것인지, 승객을 적재할 것인지를 규정할 수 있을 것이다.이 정보를 제공하면 응용 프로그램은 그 용도에 적합한 가장 좋은 차량 유형을 되돌려줍니다.이 게임은 사용자가 자신의 선택을 입력하고 대답할 수 있도록 하는 간단한 컨트롤러 프로그램이 될 것이다.
이 점을 설명하기 위해서 나는 코드를 상당히 간단하게 유지했다.전체 콘솔의 코드는 다음과 같습니다.
 static void Main(string[] args)
        {
            var requirements = new VehicleRequirements();

            Console.WriteLine( "To Build a Vehicle answer the following questions");

            Console.WriteLine("How many wheels do you have ");
            var wheels = Console.ReadLine();
            int wheelCount = 0;

            if (!int.TryParse(wheels, out wheelCount))
            {
                wheelCount= 1;
            }

            requirements.NumberOfWheels = wheelCount;

            Console.WriteLine("Do you have an engine ( Y/n )");
            var engine = Console.ReadLine();
            switch (engine)
            {
                case "Y":
                    requirements.Engine = true;
                    break;
                case "N":
                    requirements.Engine = false;
                    break;
                default:
                    requirements.Engine = false;
                    break;
            }

            Console.WriteLine("How many passengers will you be carrying ?  (1 - 10)");

            var passengers = Console.ReadLine();
            var passengerCount = 0;

            if (!int.TryParse(passengers, out passengerCount))
            {
                passengerCount = 1;
            }

            requirements.Passengers = passengerCount;


            Console.WriteLine("Will you be carrying cargo");

            var cargo = Console.ReadLine();
            switch (cargo)
            {
                case "Y":
                    requirements.Engine = true;
                    break;
                case "N":
                    requirements.Engine = false;
                    break;
                default:
                    requirements.Engine = false;
                    break;
            }

            var vehicle = GetVehicle(requirements);

           Console.WriteLine(vehicle.GetType().Name);
        }

비록 이 절의 코드는 이 점에서 상당히 혼란스럽고 읽기 어렵다 (이 단계는 심사숙고한 것이다. 왜냐하면 우리는 미래의 문장에서 토론할 것이기 때문이다!)사용자에게 한 그룹의 문제를 묻고 정의된 VehicleRequirements 에 답을 추가한 후에 이를 방법에 전달하면 이 방법은 다음에 호출될 것이다. Abstract Factory 나는 곧 설명할 것이다.GetVehicle 방법은 IVehicle 인터페이스를 실현하는 클래스의 실례를 되돌려줍니다.
 private static IVehicle GetVehicle(VehicleRequirements requirements)
        {
            var factory = new VehicleFactory();
            IVehicle vehicle;

            if (requirements.HasEngine)
            {
                return factory.MotorVehicleFactory().Create(requirements);
            }

           return factory
                .CycleFactory().Create(requirements);

        }
이런 방법에서 우리는 실제로 추상적인 공장의 실현이나 공장의 공장을 보기 시작했다.
이 인위적인 예에서 우리의 방법은 우리가 제조하고자 하는 차량 유형에 엔진이 있는지 검사하고 이 데이터에 따라 우리가 자동차를 제조하고 싶은지 페달 구동 차량을 선택하여 적당한 공장으로 방향을 바꾸어 차량을 제조할 것이다.이상적인 상황에서 당신은 추상적인 공장 자체를 선택하는 것을 연기할 수 있지만, 나는 단지 추상적인 공장 종류를 사용하면 우리는 여전히 어느 공장을 사용해야 할지 결정할 수 있다는 것을 설명하고 싶을 뿐이다.
추상류에 정의된 두 가지 방법은 모두 우리에게 대상 실현 IVehicle 인터페이스를 제공할 것이다.응용 프로그램은 대상의 최종 유형을 제어하지 않지만, 일부 기준에 따라 대상을 구축할 공장을 선택할 수 있다.
우리의 추상적인 공장은 사실상 하나abstract류로 두 가지 방법으로 정의되어 다른 두 개의 공장을 실현해야 한다.이 두 가지 방법도 IVehicleFactory의 실현에 불과하다는 것을 알게 될 것입니다.
  public abstract class AbstractVehicleFactory
    {
        public abstract IVehicleFactory CycleFactory();
        public abstract IVehicleFactory MotorVehicleFactory();

    }
이 종류는 추상적인 종류일 뿐 코드를 전혀 실현하지 못했다.만약 필요하다면, 우리는 기본적인 실현 코드를 가지고 있으며, 필요하다면, 이 코드들을 덮어쓸 수 있다.그러나 나의 목적에서 나는 단지 그것들을 뿌리로 남겨 두었을 뿐이다.
이 유형은 두 개의 서로 다른 공장의 실현을 지원하고 각 공장은 서로 다른 차량 유형으로 돌아가는 것을 책임진다.우리의 예에서 자전거나 자동차.
우리의 추상적인 공장류의 실제 실현은 다음과 같다.
 public class VehicleFactory : AbstractVehicleFactory
    {
        public override IVehicleFactory CycleFactory()
        {
           return new Cyclefactory(); 
        }

        public override IVehicleFactory MotorVehicleFactory()
        {
            return new MotorVehicleFactory();
        }
    }
사실 우리의Vehicle Factory류의 실현은 나쁜 인코딩 실천으로 여겨질 수 있다. 단지 전달 방법일 뿐이다. 그러나 나는 일부러 이 점을 실현하여 우리의 방법이 최종적으로 대체 공장을 호출할 가능성이 높다는 것을 설명한다.

A Pass Through Method is one that does little except invoke another method, whose signature is similar or identical to that of the calling method.
This typically denotes there is not a clean division between classes

--- John Ousterhout - A Philosophy of Software Design


만약 우리가 그 중의 한 공장의 실현, 즉 CycleFactory 을 본다면, 당신은 내가 실제로 Factory Method Pattern 을 사용하여 되돌아갈 대상을 만드는 실례를 선택했다는 것을 알게 될 것입니다.제가 이 점을 선택한 것은 다른 점을 강조하기 위해서입니다. 개발자로서 당신은 이 모델을 교환하여 사용할 수 있고 다른 모델과 일치할 수 있습니다.
 public class Cyclefactory : IVehicleFactory
    {
        public IVehicle Create(VehicleRequirements requirements)
        {
            switch (requirements.Passengers)
            {
                case 1:
                    if(requirements.NumberOfWheels == 1) return new Unicycle();
                    return new Bicycle();
                case 2:
                    return new Tandem();
                case 3:
                    return new Tricyle();
                case 4:
                    if (requirements.HasCargo) return new GoKart();
                    return new FamilyBike();
                default:
                    return new Bicycle();
            }
       }
    }
비록 이것은 정성들여 설계한 예이지만, 그것은 확실히 공장 개념 중의 공장 개념에 대한 설명과 강조이다.
나는 가능한 한 이 예시의 논리를 보존하려고 했지만, 이 공장이 최종적으로 호출용 클라이언트의 대상을 실례적으로 전달하는 것을 책임지고 있음을 설명하려고 했다.이러한 사실을 강조한다. 즉, 클라이언트는 대상의 창설에 관심을 가질 필요가 없고 되돌아오는 대상의 결정점은 몇 층으로 구분된다.
우리의 공장 방법은 현재 어떤 규칙 엔진을 자유롭게 실현하고 수요에 따라 차량을 만들 수 있다.
이것은 관심사를 분리하여 테스트 가능성을 높일 수 있다.이 간단한 예시에서도 클라이언트는 입력된 데이터에만 관심을 가져야 한다는 것을 알 수 있습니다. 즉, 가능한 한 원본에 가까운 데이터를 검증한 다음에 이 데이터를 추상적인 공장 클래스에 전달하고 필요한 공장에 전파하여 대상을 만들 수 있습니다.
바로 이 특성으로 인해 추상적인 공장 방법은 유행하고 강력한 모델이 되어 단원 테스트 코드에 더욱 큰 기회를 제공할 수 있다.이 모델을 다른 모델과 결합하여 사용하면 코드의 테스트 가능성을 더욱 강화할 수 있다.

공장을 재구성하다.


우리의 추상적인 공장 코드가 운행되고 있지만, 솔직히 말하자면, 그것은 상당히 더러운 코드이며, 실제로는 우리가 추상적인 공장 모델을 사용하여 얻을 수 있는 모든 장점을 제공하지 않는다.몇 가지 이유로 나는 앞에서 언급한 적이 있다.
우리 공장 모델에 대해 경미한 재구성을 진행하자.첫 번째 문제는 클라이언트 응용 프로그램의 옵션을 삭제하여 어느 공장을 사용할지 결정할 필요가 없거나 확장할 수 있도록 해야 한다는 것이다.
하나의 옵션을 설명하기 위해서 우리는 완전한 재구성을 하고 코드를 정리할 것이다.나의 첫 번째 선택은 싫은 전달 방법을 삭제하는 것이다. 그들은 실제로 깨끗한 추상을 제공하지 않았다. 사실상 우리는 우리의 유형에 두 가지 공장 방법의 필요성을 삭제하고 하나만 제공할 수 있다.이것은 우리의 교실을 더욱 쉽게 이해하고 어떤 잘못도 없앨 수 있는 기회가 될 것이다.
우리의 사례에서 우리는 고객에게 선택을 제공한다Factory.우리의 새로운 추상적인 공장류를 재구성하는 데는 현재 오직 한 가지 방법이 있다.
    public abstract class AbstractVehicleFactory
       {
           public abstract IVehicle Create();
       }
이로써 우리는 공장류가 실현하는 재구성을 계속 완성할 것이다.
private readonly IVehicleFactory _factory;
        private readonly VehicleRequirements _requirements;

        public VehicleFactory(VehicleRequirements requirements)
        {
            _factory = requirements.HasEngine  ? (IVehicleFactory) new MotorVehicleFactory() : new Cyclefactory();
            _requirements = requirements;

        }
        public override IVehicle Create()
        {
           return _factory.Create(_requirements);
        }

우리는 실제로 구조 함수를 사용하여 수요를 전달하고 데이터를 사용하여 어느 공장이 우리가 선택한 차량을 만드는 데 가장 적합한지 확인할 수 있다는 것을 알게 될 것이다.이것은 고객이 잘못된 공장을 사용할 위험을 최대한 낮출 것이다.
클라이언트GetVehicle 방법의 복잡성이 크게 낮아져서 그들은 현재 데이터를 검사하고 어느 공장을 사용하는지 확정할 필요가 없다.그들이 해야 할 일은 구조 함수에서 전달VehicleRequirements을 하고 Create 방법을 호출하는 것이다. 모든 신기한 일이 발생할 것이다.
 private static IVehicle GetVehicle(VehicleRequirements requirements)
        {
            var factory = new VehicleFactory(requirements);
            return factory.Create();
        }
우리가 여기서 얻은 성과는 추상적인 중요한 방면이다

An Abstraction is a simplified view of an entity, which omits unimportant details.
--- John Ousterhout - A Philosophy of Software Design


우리는 성공적으로 Pull Complexity Downwards 사용자의 복잡성을 차단하고 그들에게 사용하기 쉬운 인터페이스를 제공했다.

When developing a module, look for opportunities to take a little bit of extra suffering upon yourself in order to reduce the suffering of your users.

--- John Ousterhout - A Philosophy of Software Design


결론


추상적인 공장 모델은 개발자로 하여금 관련 대상의 족을 통용적으로 정의하고 수요에 따라 이러한 대상의 실제 구체적인 실현을 실현할 수 있게 한다.
추상적인 공장 모드는 C#에서 매우 흔히 볼 수 있다.net Framework의 라이브러리는 표준 구성 요소를 확장하고 사용자 정의하는 방법을 제공합니다.

좋은 웹페이지 즐겨찾기