팩토리 메소드 디자인 패턴이 클래스를 가지고 개별적으로 호출하는 것보다 더 유용한 이유는 무엇입니까?


32

"Gang of Four"디자인 패턴에는 Factory 메소드가 있습니다.

class Factory(product)
  case product
  when a
    new A
  when b
    new B
  when c
    new C
end

new Factory(a)

왜 이런 일이 세 가지 클래스가 갖는보다 더 유용 a, bc과 개별적으로 호출?


1
정확히 무엇을 의미합니까? 세 가지를 모두 인스턴스화하지 않는 이유는 무엇입니까? 이게 네가 말하는거야?
Neil

1
@ 닐 아니요, 팩토리 패턴에서 모든 클래스는 형제로 존재합니다. a, b, c 클래스에 간접적으로 액세스하기 위해 팩토리를 호출하는 이유는 무엇입니까?
alt

3
추상적 인 공장의 가까이 아무것도 경우이 사실은, 나에게 팩토리 메소드 패턴처럼 보이지 않는
JK.

2
디자인 타임에 3 개의 클래스 중 어떤 인스턴스를 인스턴스화해야하는지 알 수 없기 때문입니다.
MrWhite

2
@ jk : 아니요, 실제로는 그렇지 않습니다. programmers.stackexchange.com/questions/81838/…
pdr

답변:


54

당신의 예는 충분히 복잡하지 않기 때문입니다. 이러한 간단한 시나리오의 경우 고급 패턴을 사용하는 것이 이치에 맞지 않습니다.

그러나 A, B 또는 C를 구성하기 위해 제품 이상을 알아야하고 해당 지식에 직접 액세스 할 수없는 경우 유용합니다. 그런 다음 팩토리를 사용하여 필요한 오브젝트를 생성하기위한 지식 센터 역할을합니다.

해당 객체는 팩토리가 제공 할 수있는 일부 객체 X에 대한 참조가 필요할 수 있지만 A, B 또는 C를 생성하려는 장소의 코드는 X에 액세스 할 수 없거나 X에 액세스 할 수 없어야합니다. A와 B를 만들지 만 Y 유형이 있으면 C를 만듭니다.

또한 일부 객체는 생성하기 위해 20 개의 종속성이 필요할 수 있습니다. 그럼 뭐야? 접근 할 수없는 장소에서 이러한 종속성을 찾으려하면 문제가 될 수 있습니다.


13
팩토리 패턴이 항상 최선의 접근 방법이 아님을 분명히하기 위해 +1.
Neil

1
당신의 예는 충분히 복잡하지 않기 때문입니다. 이러한 간단한 시나리오의 경우 고급 패턴을 사용하는 것이 이치에 맞지 않습니다. 이 경우 어떻게 하시겠습니까? 조건부 구성을 인라인합니까?
pdr

제품을 가져 와서 재사용 할 수 있도록 필요한 것을 반환하는 방법 일 수 있으므로 인라인 일 필요는 없습니다. 그러한 방법이 더 커지거나 다른 여러 클래스에서 사용되는 경우 다른 클래스로 리팩토링 할 수 있습니다.
Mateusz 2016

이러한 이유로 패턴을 팩토리 메소드라고합니다. 팩토리 메소드가되기 위해 메소드가 다른 클래스에있을 필요는 없습니다.
pdr

나는 그 안에 "방법"을 놓쳤으므로 당신은 올바른 아저씨입니다.
Mateusz

23

팩토리 패턴은 일반적으로 그보다 더 복잡합니다. 팩토리는 어떤 기준을 생성 / 반환할지 결정합니다. 대신 팩토리를 사용하지 않으면 코드의 여러 위치에서 해당 코드를 반복적으로 사용하게됩니다.

예를 들어 다음 사항을 고려하십시오. DB에서 데이터를로드해야하지만 많은 데이터와 통합하기위한 중앙 DB가 하나 있고 각 dev-PC의 메모리에 하나는 더 작습니다. 코드에서 팩토리 DB 핸들 을 가져 오도록 요청하고 팩토리 는 구성 파일에 따라 그중 하나를 반환합니다.


20

팩토리 메소드 패턴은 호출 클래스에서 의사 결정 프로세스를 추상화합니다. 여기에는 몇 가지 장점이 있습니다.

재사용 여러 곳에서 인스턴스를 만들고 싶다면 조건을 반복 할 필요가 없으므로 새 클래스를 추가 할 때 클래스를 놓칠 위험이 없습니다.

단위 테스트 가능성. 팩토리에 대해 3 가지 테스트를 작성하여 올바른 조건에서 올바른 유형을 리턴하는지 확인할 수 있습니다. 그러면 호출 클래스가 팩토리를 호출하는지 여부와 리턴 된 클래스에서 필요한 메소드를 테스트하기 만하면됩니다. 팩토리 자체 또는 구체적인 클래스의 구현에 대해서는 아무것도 알 필요가 없습니다.

확장 성. 누군가 우리가이 팩토리에 새로운 클래스 D를 추가해야한다고 결정할 때, 단위 테스트 나 구현 모두에 대한 호출 코드 중 어느 것도 알려주지 않아도됩니다. 우리는 단순히 새로운 클래스 D를 만들고 팩토리 메소드를 확장합니다. 이것은 공개 폐쇄 원칙의 정의입니다 .

예를 들어 테스트 중에 클래스 D를 켜거나 끌 수있는 경우와 같이 상황에 따라 새 팩토리 클래스를 만들어 핫 스왑 가능하게 만들 수도 있습니다. 이 상황에 한 번만 발생했지만 매우 유용했습니다.

이미 언급했듯이 팩토리 패턴이 항상 진행되는 것은 아닙니다. 그러나 조건부 인스턴스화를 볼 수있는 곳이라면 어디든 생각해야합니다.


14

팩토리 패턴의 주요 장점은 두 가지입니다.

  1. 제품의 구현이 필요한 장소는 제품을 구성하는 방법을 알 필요가 없습니다. 공장은 그 정보를 보유하고 있습니다.

    특정 생성자에 전달할 인수를 알고 싶습니까? 또는 어떤 의존성을 주입해야합니까? 또는 데이터베이스가 완전히 구성된 후 구현 클래스를 데이터베이스에 등록하는 방법은 무엇입니까? 아니? 공장에서 그 모든 것들을 보자.

  2. 제품 구현이 필요한 장소는 모듈 설명 시점 (즉, 컴파일 타임)에 구현 클래스의 이름이 무엇인지 알 필요가 없습니다.

    따라서 a아무 상관이 없습니다 A. "구축 대상"은 이름뿐만 아니라 원하는 비 기능적 속성으로 설명 될 수 있습니다. 이것은 훨씬 더 유연합니다.

단점은 무엇을 만들고 어떻게해야하는지 아는 곳에서 공장을 사용할 때 더 복잡해진다는 것입니다. 그래도 해결 방법은 간단합니다. 의미가 맞지 않을 때는 팩토리를 사용하지 마십시오!


2

수업은 '사람'이라는 관점에서 디자인 패턴에 대해 생각하고 싶습니다. 패턴은 사람들이 서로 이야기하는 방식입니다.

나에게 공장 패턴은 고용 기관과 같습니다. 다양한 수의 근로자가 필요한 사람이 있습니다. 이 사람은 그들이 고용 한 사람들에게 필요한 정보를 알고 있을지 모르지만 그게 전부입니다.

따라서 신입 사원이 필요할 때 고용 기관에 연락하여 필요한 것을 알려줍니다. 이제 실제로 누군가를 고용하려면 혜택, 적격성 검증 등 많은 것을 알아야합니다. 그러나 고용하는 사람은이를 알 필요가 없습니다. 고용 기관이 모든 것을 처리합니다.

같은 방식으로 팩토리를 사용하면 소비자는 자신이 생성 된 방법이나 종속성이 무엇인지에 대한 세부 정보를 알 필요없이 새로운 객체를 만들 수 있습니다. 실제로 원하는 정보 만 제공하면됩니다.

예의


1

팩토리 패턴은 가장 많이 사용되고 남용 된 디자인 패턴입니다.

간단한 생성자가 적절할 때 Factory 클래스가 코딩되는 수많은 경우를 보았습니다.

다음과 같은 경우가 아니면 팩토리 클래스를 사용하지 마십시오.

  • 당신은 외부 자원에 의존하지만 아직 정확히 어느 것을 알지 못합니다.
  • 건설 비용이 많이 들고 한 번만 만들고 여러 번 재사용하고 싶습니다.
  • 새 인스턴스를 생성하는 것은 이미 생성 된 인스턴스에 따라 다릅니다 (예 : 연결은 5 개만 가능하거나 마지막으로 사용한 번호보다 하나 더 많은 연결 ID 번호를 사용해야 함).

0

서브 클래스를 인스턴스화 할 때 팩토리 메소드를 사용하고 클라이언트 코드가 인스턴스화 할 특정 서브 클래스를 결정할 책임이 없습니다.

인스턴스화 할 클래스를 변경해야 할 때 클라이언트 코드를 변경하지 않아도되므로 유용합니다. 기존 코드를 변경하는 것은 일반적으로 오류가 발생하기 쉽기 때문에 나쁜 습관입니다.

예를 들어 서브 클래스가있을 수 있는데, 각 서브 클래스는 오름차순으로 데이터를 정렬하지만 다른 방식으로 정렬합니다. 각 방법은 특정 종류의 데이터에 적합합니다. 예 : 부분적으로 정렬 된 데이터, 숫자 인 데이터 등. 클라이언트 코드는 데이터 인쇄 만 처리하는 클래스입니다. 클라이언트 클래스에서 어떤 정렬 클래스를 인스턴스화할지 결정하는 코드가 있으면 복잡한 클래스가됩니다. 다시 말해, 하나 이상의 책임이있는 경우,이 경우 최적의 정렬 클래스를 결정하고 데이터를 인쇄합니다. 어떤 정렬 클래스를 인스턴스화 할 것인지를 결정하는 코드를 팩토리 클래스에 넣음으로써 문제를 분리하여 어떤 정렬 서브 클래스가 인스턴스화되는지를 변경할 때마다 클라이언트 클래스를 변경할 필요가 없습니다.

클래스를 인스턴스화하는 방법 또는 대상에서 자체 결정 변경을 예측할 수 있다면 팩토리 클래스를 사용하는 것이 합리적입니다. 클래스가 자신의 책임에 집중하도록 돕고 결과적으로 관련이없는 기존 코드를 수정하지 않아도됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.