이 ShapeFactory가 인스턴스화 할 오브젝트를 판별하기 위해 조건문을 사용하는 이유는 무엇입니까? 나중에 다른 클래스를 추가하려면 ShapeFactory를 수정하지 않아도됩니까? 이것이 공개 폐쇄 원칙을 위반하지 않는 이유는 무엇입니까?
이 ShapeFactory가 인스턴스화 할 오브젝트를 판별하기 위해 조건문을 사용하는 이유는 무엇입니까? 나중에 다른 클래스를 추가하려면 ShapeFactory를 수정하지 않아도됩니까? 이것이 공개 폐쇄 원칙을 위반하지 않는 이유는 무엇입니까?
답변:
기존의 객체 지향적 지혜는 if
문장 을 피하고 이를 추상 클래스의 서브 클래스에서 재정의 된 메소드의 동적 디스패치로 대체하는 것입니다. 여태까지는 그런대로 잘됐다.
그러나 팩토리 패턴의 요점은 개별 서브 클래스에 대해 알 필요가없고 추상 수퍼 클래스로만 작업해야한다는 것 입니다. 아이디어는 팩토리가 인스턴스화 할 특정 클래스보다 공장을 더 잘 알고 있으며 수퍼 클래스가 게시 한 메소드로만 작업하는 것이 좋습니다. 이것은 종종 사실이며 귀중한 패턴입니다.
따라서 팩토리 클래스를 작성하는 것이 if
진술을 포기할 수있는 방법은 없습니다 . 그것은이다 호출자에 특정 클래스를 선택하는 부담이 이동할 것입니다 정확히 패턴을 방지하기 위해 가정 무엇을. 모든 원칙 (사실, 절대 어떤 원리는 절대 없다), 당신은이 패턴을 사용하는 경우 당신은 그것에서 이익이를 사용하지의 이익보다 큰 것으로 가정 것입니다 if
.
if
s 없이 팩토리 패턴을 작성하는 것이 완벽하게 가능합니다 . 이를 달성하는 간단한 예는 @ BЈовић의 답변을 참조하십시오. 공감.
이 예는 조건문이 가장 단순하기 때문에 아마도 조건문을 사용합니다. 보다 복잡한 구현은 맵이나 구성을 사용하거나 클래스가 스스로 등록 할 수있는 일종의 레지스트리를 사용할 수 있습니다. 그러나 클래스 수가 적고 드물게 변경되는 경우 조건부 사용에 아무런 문제가 없습니다.
미래에 새로운 하위 클래스에 대한 지원을 추가하기 위해 조건부를 확장하는 것은 실제로 개방 / 폐쇄 원칙을 위반하는 것입니다. "올바른"솔루션은 동일한 인터페이스로 새 팩토리를 작성하는 것입니다. 즉, O / C 원칙 준수는 항상 KISS 및 YAGNI와 같은 다른 설계 원칙과 비교되어야합니다.
즉, 표시된 코드는 공장의 개념을 보여주기 위해 설계된 코드의 예입니다. 예를 들어 예제와 같이 null을 반환하는 것은 실제로 나쁜 스타일이지만 더 정교한 오류 처리는 요점을 모호하게합니다. 예제 코드는 프로덕션 품질 코드가 아니므로 예상하지 마십시오.
패턴 자체는 OCP (Open / Closed Principle)를 위반하지 않습니다. 그러나 패턴을 잘못 사용하면 OCP를 위반하게됩니다.
이 질문에 대한 간단한 대답은 다음과 같습니다.
제공된 예제에서 기본 기능은 Circle, Rectangle 및 Square의 세 가지 모양을 지원합니다. 향후 Triangle, Pentagon 및 Hexagon을 지원해야한다고 가정하십시오. OCP를 위반 하지 않고이 작업을 수행하려면 새 모양 (이라고 함 AdvancedShapeFactory
) 을 지원하는 추가 팩토리를 생성 한 다음 AbstractFactory 를 사용 하여 필요한 모양을 생성하기 위해 생성해야하는 팩토리를 결정해야합니다.
Abstract Factory 패턴에 대해 이야기하고 있다면 의사 결정은 종종 Factory 자체가 아니라 응용 프로그램 코드에 있습니다. 그것은 팩토리가 생성 한 객체를 사용할 클라이언트 코드로 인스턴스화하고 전달할 구체적인 팩토리를 선택하는 코드입니다. https://en.wikipedia.org/wiki/Abstract_factory_pattern 에서 Java 예제의 끝을 참조하십시오.
의사 결정이 반드시 if
진술을 의미하지는 않습니다 . 구성 파일에서 구체적 팩토리 유형을 읽고 맵 구조 등에서 파생 할 수 있습니다.
이 팩토리의 클래스 수준에서 Open-Close에 대해 생각하면 시스템을 Close-Close로 다른 클래스를 만듭니다. 예를 들어 하나의 Shape를 취하는 다른 클래스가 있고 면적을 계산하는 경우 (일반적인 예)이 클래스는 OpenClose 수정하지 않고 새로운 유형의 도형에 대한 면적을 계산할 수 있습니다. 그런 다음 모양을 그리는 또 다른 클래스, N 모양을 취하고 더 큰 클래스를 반환하는 다른 클래스가 있으며 일반적으로 모양을 처리하는 시스템의 다른 클래스는 (적어도 모양에 대해) 닫힘이라고 생각할 수 있습니다. 설계를 살펴보면 공장에서 나머지 시스템을 개방 및 폐쇄 할 수 있으며 공장 자체는 개방되지 않습니다.
물론 어떤 종류의 동적 로딩을 통해이 팩토리를 오픈 클로즈로 만들 수 있으며 전체 시스템은 오픈 클로즈가 될 수 있습니다 (예를 들어 클래스 경로에 항아리를 떨어 뜨리는 새로운 모양을 추가 할 수 있음). 모든 시스템이 플러그 가능한 기능을 필요로하는 것은 아니며 모든 시스템이 완전 개방형 일 필요는 없습니다.
그것은 모두 구현 방법에 달려 있습니다. std::map
객체를 생성하는 함수에 대한 함수 포인터를 보유 하는 데 사용할 수 있습니다 . 그런 다음 개방 / 폐쇄 원칙을 위반하지 않습니다. 또는 스위치 / 케이스.
어쨌든 팩토리 패턴이 마음에 들지 않으면 항상 의존성 주입을 사용할 수 있습니다.