문제

의존성 주입을 올바르게 구현하는 방법 중 하나는 객체 생성을 비즈니스 로직과 분리하는 것입니다. 일반적으로 여기에는 객체 생성을 위해 공장을 사용하는 것이 포함됩니다.

이 시점까지, 나는 공장을 사용하는 것을 진지하게 고려한 적이 없으므로이 질문이 조금 단순한 것처럼 보이면 사과드립니다.

내가 실행하는 공장 패턴의 모든 예에서, 나는 항상 매개 변수화가없는 매우 간단한 예를 봅니다. 예를 들어, 여기에서 도난당한 공장이 있습니다 Misko Hevery 's 훌륭한 "새로운"연산자에 대해 생각하는 방법 기사.

class ApplicationBuilder {
  House build() {
    return new House(new Kitchen(
               new Sink(),
               new Dishwasher(),
               new Refrigerator())
           );
  }
}

그러나 내가 지은 각 집을 원한다면 이름이있는 경우 어떻게됩니까? 이 코드를 다음과 같이 다시 쓰면 여전히 공장 패턴을 사용하고 있습니까?

class ApplicationBuilder {
  House build( const std::string & house_name) {
    return new House( house_name,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
}

내 공장 메소드 호출은 다음과 같이 변경되었습니다.

ApplicationBuilder builder;
House * my_house = builder.build();

이에:

ApplicationBuilder builder;
House * my_house = builder.build("Michaels-Treehouse");

그건 그렇고 : 비즈니스 논리에서 인스턴스베이션하는 객체를 분리하는 개념이 훌륭하다고 생각합니다. 단지 내 상황에 어떻게 적용 할 수 있는지 알아 내려고 노력하고 있습니다. 저를 혼란스럽게하는 것은 공장 패턴에서 내가 본 모든 예제가 어떤 매개 변수도 build () 함수에 전달하지 않는다는 것입니다.

분명히 : 나는 집의 이름을 인스턴스화하기 전까지는 집의 이름을 모른다.

도움이 되었습니까?

해결책

나는 당신의 이름 예제에서와 같이 고정 된 인수 세트를 사용하는 많은 예를 보았고 그들도 직접 사용했으며 그것에 잘못된 것을 볼 수 없습니다.

그러나 많은 튜토리얼이나 작은 기사가 구성된 개체에 매개 변수를 전달하는 공장을 보여주지 않는 좋은 이유가 있습니다. 거의 임의의 인수 수를 전달하는 것은 불가능합니다 (6 인수와 같은 제정신 한계의 경우에도). 전달한 각 매개 변수는 다음과 같이 받아 들여야합니다 const T& 그리고 T& 당신이 그것을하고 싶다면 일반.

그러나보다 복잡한 예를 보려면 기하 급수적으로 성장하는 오버로드 세트 (각 매개 변수, const 및 non -onst 버전) 및 완벽한 전달 전혀 불가능합니다 (예 : 임시는 임시로 전달됩니다). 다음 C ++ 표준의 경우 해당 문제가 해결됩니다.

class ApplicationBuilder {
  template<typename... T>
  House *build( T&&... t ) {
    return new House( std::forward<T>(t)...,
                      new Kitchen(new Sink(),
                                  new Dishwasher(),
                                  new Refrigerator())
                    );
  }
};

그렇게하면 전화 할 수 있습니다

builder.build("Hello", 13);

그리고 그것은 돌아올 것입니다

new House("Hello", 13, new Kitchen(new Sink(...

위에서 링크 한 기사를 읽으십시오.

다른 팁

이 매개 변수를 공장에 추가하는 것이 왜 잘못되었는지 알 수 없습니다. 그러나 공장에서 만든 모든 개체에 유용하지 않을 수있는 많은 매개 변수를 추가해서는 안됩니다. 당신이 그렇게한다면, 당신은 공장의 많은 장점을 잃을 것입니다!

허용 될뿐만 아니라 그렇습니다 흔한 매개 변수를 공장 방법으로 전달합니다. 체크 아웃 몇 가지 예. 일반적으로 매개 변수는 공장에 무엇을 만들어야하는지 알려주는 유형이지만 객체를 작성하는 데 필요한 다른 정보를 추가 할 수없는 이유는 없습니다. 나는 당신이하는 일이 괜찮다고 생각합니다.

공장의 아이디어는 클래스/인터페이스 인스턴스를 제공하므로 매개 변수를 전달하는 데 아무런 문제가 없습니다. 있다면, 매개 변수를 새로운 ()로 전달하는 것은 나쁘다.

나는 Benoit에 동의합니다. 그러나 SQL 연결과 같은 것을 생성하기위한 공장을 생각해보십시오.이 경우 공장과의 연결에 대한 정보를 전달해야합니다. 공장은 해당 정보를 사용하여 올바른 서버 프로토콜 등을 사용합니다.

물론, 왜 ..!?

매개 변수를 전달하는 데있어 좋은 점은 콘크리트 물체의 구현을 숨길 수 있다는 것입니다. 예를 들어, 게시 된 코드에서 매개 변수를 생성자에게 전달합니다. 그러나 구현을 변경하여 initiailze 방법. 매개 변수를 공장 방법에 전달하면 발신자로부터 객체를 구성하고 초기화하는 특성을 숨 깁니다.

그러나 Loki :: Factory를 살펴보면 Boost와 같은 구현도 있습니다. 내가 정기적으로 다른 맛으로 사용하는 몇 가지 예제 코드 :

typedef loki :: singletonholder <loki :: factory <component, std :: string, loki :: typelist <const datacollection &, loki :: typleist <Game*, loki :: nullType>>>>>>>>>>>>>>>>>>

이것은 첫눈에 조금 이상하게 보일지 모르지만,이 짐승과 그것이 얼마나 강력한 지 설명하겠습니다. 기본적으로 우리는 공장을 보유하는 싱글 톤을 만듭니다. 대부분의 매개 변수는 싱글 톤에 대한 것입니다. 구성 요소는 우리의 제품입니다. std :: string은 우리의 생성 ID 유형입니다. (이것은 매크로를 사용하여 정의 할 수 있습니다). 이 줄 후에는 다음과 같습니다.

componentFactory :: instance (). CreateObject ( "SOMESTRINGSASSOCIATIONWITHCONCRETETYPE", andAtacollection, AgamePointer);

객체를 만들려면 하나를 등록하려면 componentFactory :: instance (). register ();. 현대 C ++ 디자인 책의 세부 사항에 대한 훌륭한 장이 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top