할인 모델에 적용 할 디자인 패턴이 있습니까?


34

할인 모델을 구현하기위한 알려진 디자인 패턴이 있습니까?

할인 모델의 의미는 다음과 같습니다.

  1. 고객이 제품 X, 제품 Y 및 제품 Z를 구매하면 10 % 또는 $ 100의 할인을받습니다.

  2. 고객이 Product X 100 유닛을 구매하면 15 % 또는 $ 500의 할인을받습니다.

  3. 고객이 작년에 $ 100K 이상을 가져 오면 20 % 할인을받습니다

  4. 고객이 제품 X 2 개를 구매 한 경우 제품 X 1 개 (또는 제품 Y) 1 개가 무료로 제공됩니다.

  5. ...

위의 모든 시나리오를 처리하기 위해 적용 할 수있는 일반적인 패턴이 있습니까? 나는 몇 가지 모델을 생각하고 있지만 일반적인 모델을 발견 할 수는 없습니다.


IIRC 제가 할인과 관련된 예제로 본 모든 튜토리얼은 (많은) 전략 패턴을 제안합니다
gnat

2
@ Kanini 이것은 실제 문제입니까? 이 경우이 시스템은 실시간 또는 지연된 시스템입니까? 이러한 규칙이 규칙 엔진 또는 데이터베이스 값으로 표시됩니까? 할인 검색은 우선 순위에 따라 계층 적입니까? 전략 패턴은 대부분의 경우에 효과가 있지만 규칙을 적용하려면 규칙을 고려해야합니다.
Ubermensch

3
또한 누군가 누군가 제품 X 2 개, 제품 Y 1 개, 제품 Z 1 개를 구매하는 경우 10 %와 추가 제품 X를 모두 얻을 수 있습니까?
Ubermensch

@gnat 해당 튜토리얼 중 일부에 대한 링크를 참조하십시오.
user16764

답변:


18

문제가 주어진 상황에서 여러 할인을 적용해야하는 경우 책임 체인 패턴 을 고려할 수 있습니다 .

간단히 말해서 처리하려는 정보를 첫 번째 프로세서로 전달하고 결과를 반환하기 전에 추가 프로세서로 전달할지 여부를 결정합니다.

이렇게하면 호출 코드를 변경하지 않고도 프로세서의 구조와 순서를 변경할 수 있습니다.


책임의 사슬은 또 다른 좋은 것입니다. 전략과 결합 될 수도 있습니다. 하나의 할인 만 적용 할 수있는 경우 각 전략은 다른 전략과 연결됩니다. 각 체인은 할인을 계산하고 (고객이 자격이있는 경우)이를 이전 할인과 비교 한 후 고객, 주문 및 할인 데이터를 다음 체인으로 전달합니다. +1.
Thomas Owens

1
저의 의견이지만 "책임의 체인"이이 경우에 대해 과도하게 설계되었을 가능성이 높습니다. 할인 모델의 간단한 목록 (필요한 경우 주문 번호가있는)이이를 수행해야합니다. 모든 고객을 동일하게 대우해야하기 때문에 목록 자체는 고객 및 그의 주문과 독립적입니다. 할인 모델 목록이 런타임시 매우 동적으로 매우 자주 변경되는 경우 "책임 체인"이 더 적합합니다.
Doc Brown

11

전략, 데코레이터 및 상태 패턴은 잠재적 출발점으로 눈에 out니다. 2는 주문 상태에 의존하고 3은 기간 내에 고객의 상태에 의존하기 때문에 상태는 2 또는 3에 특히 유용 할 수 있습니다. 전략과 데코레이터는 전략을 사용하여 여러 주문 가격 계산 알고리즘을 구현하고 데코레이터를 사용하여 주문에 새로운 할인을 추가 할 수 있습니다.

그러나 디자인 패턴은 모델 일뿐입니다. 적용되는 단일 패턴이 아니라 패턴 시스템이있을 수 있습니다. 또한 설명 된 모델을 솔루션에 더 잘 맞게 수정하십시오. 패턴이 있다고 말할 수 있도록 패턴을 강제하는 것보다 패턴을 강요하는 것보다 좋은 디자인을 갖는 것이 좋습니다.


그것은 실제로 상태 패턴이 의도 한 것이 아닙니다. 그렇지 않습니까?
pdr

@ pdr 왜 안되는지 모르겠습니다. 그러나 그것은 당신의 구현에 달려 있습니다. 고객 오브젝트가 고객 종속 할인을 추적하는 경우 고객이받을 수있는 할인을 리턴하는 조작이있을 수 있습니다. 고객이 물건을 구매함에 따라 속성이 변경되고이 메소드 구현은 상태 패턴을 통해 변경됩니다.
Thomas Owens

1
흠, 무슨 말인지 알 겠어. 고객이 응용 프로그램의 반영구적 개체인지 아니면 데이터베이스에 있고 업데이트가 필요한지 여부에 달려 있다고 생각합니다. 질문에서 명확하지 않으므로 충분히 공평합니다. +1
pdr

3
내 경험에 비추어 볼 때 이러한 종류의 할인 비즈니스 규칙은 변덕스러운 마케팅 / 영업 부서에 의해 항상 수정됩니다. 코드 기반이 아닌 데이터 기반 및 사용자 수정이 가능해야합니다. 이것이 모델 선택에 어떤 영향을 미칩니 까?
jfrankcarr

@jfrankcarr 내 마음에는 그렇지 않습니다. 어떤 종류의 구성에서 할인, 백분율 등으로 이어지는 항목 세트의 값을 채 웁니다. 내 상태 머신 전환과 데코레이터 및 전략의 속성을 동적으로 구축합니다.
Thomas Owens

10

글쎄, 나는 할인 모델을 "Precondition"과 "Discount"쌍으로 디자인 할 것이다. 여기서 "Precondition"은 메소드를 가진 클래스이다

  bool IsFulfilled(Customer c);

또는

  bool IsFulfilled(Customer c, Order o);

할인에는 방법이 void ApplyTo(Customer c)있습니다. 이를 통해 모든 유형의 전제 조건을 모든 유형의 할인과 결합 할 수 있습니다 ( "브리지 패턴"이라고 생각합니다).

고정 된 수의 전제 조건이있는 경우 특정 하위 유형 (전략 패턴)을 빌드하여 문제점을 해결할 수 있습니다. 그러나 AND, OR 및 NOT과 같은 논리 문을 사용하여 사전 조건이 매우 복잡 할 수있는 경우 조건에 대해 일종의 규칙 해석기를 더 잘 구현할 수 있습니다. 규칙은 간단한 "도메인 특정 언어"로 작성된 일반 텍스트 문자열 일 수 있습니다.

"할인"클래스도 마찬가지입니다. 다른 할인 유형에 대한 일부 하위 유형이 있거나 일부 통역사가 할인 규칙을 텍스트 형식으로 제공하는 일반적인 접근 방식을 사용할 수 있습니다.


내 직감은 이것이 그가 질문의 맥락에서 찾고있는 것일 수 있다고 제안한다
Ubermensch

4
  • 서로 다른 모든 할인이 동일하기 때문에 IDiscount 인터페이스가 필요할 것이므로 개념적으로 일반 할인으로 처리하려고합니다.

  • "이 고객의 주문"클래스에는 할인 콜렉션이 필요할 수 있습니다. 명부? 해시시? 연결된 목록? 아직 걱정하지 마십시오. 고객이 아닌 구매에 할인이 적용됩니다!

  • @jfrankcarr이 지적한 것처럼 할인 인스턴스 건물을 고객, 쇼핑 카트, 내역 등과 별도로 유지하십시오.

  • 각 할인에 대한 알고리즘 및 매개 변수가 매우 다양하고 예측할 수 없기 때문에 각 할인에 대해 다른 클래스 일 수 있습니다.

  • 할인 계산이 장바구니 변경에 응답하고 그 반대의 경우도 많은 이벤트 처리를 봅니다.

디자인 패턴 응용

  • 을 참조하십시오 strategy pattern. IDiscount는 다양한 할인 알고리즘을 구현하기위한 인터페이스입니다.
  • 을 참조하십시오 factory. 확실히 본격적인 abstract factory pattern것은 아니지만 분석 시점에서 단일 클래스입니다. 어떤 할인이 적용되는지 결정한 다음 할인을 생성 할 수있는 컨텍스트가 충분한 단일 장소가 있어야합니다. 하나의 수업. 나중에 마케팅 부서 버섯 파티로 인해 할인 적용 규칙이 폭발하더라도 추가 할인 구성 논리가 여전히이 기본 팩토리 클래스에서 통합되어야한다고 생각합니다.

  • 볼 수 있습니다 Chain of Responsibility. 이 factory아이디어 는 상호 배타적이지 않습니다 . 할인 콜렉션을 반복하는 대신 각 할인은 다음 사람에게 전화합니다. 이 경우 "고객 주문"클래스에는 할인 모음이 없습니다.

  • 책임 사슬의 "흠 ..."요소는 각 할인이 다음에 대한 참조를 갖는 것입니다. 그 의미는 순서가 중요하다는 것입니다. 그렇지 않습니다. 또한 CoR이 구현하는 개념은 하나의 개체가 요청을 처리 할 수 ​​없으므로 "다음 상위 권한까지"전달된다는 것입니다. 우리 모델은 다릅니다. 유일한 요청 은 계산하는 것입니다. 모든 할인이이 작업을 수행합니다. 출력 또는 효과는 null 일 수 있지만 모든 할인은 계산됩니다. 나는 본능적으로 더 높은 실세계 충실도에 기대어 있습니다.

가정

  • 할인은 현재 장바구니 및 / 또는 구매 내역을 기반으로합니다.
  • 0 회 이상의 할인이 적용될 수 있습니다. 상호 배타적 할인은 없습니다
  • 적절한 계산은 할인 적용 순서에 의존하지 않습니다.

어떤 변화가 있습니까?

  • 할인은 매우 다릅니다. 각 규칙을 구성하는 매개 변수의 수와 종류가 다릅니다.

  • 장바구니가 변경되면 적격 할인에 대한 인수가 변경됩니다.

  • 사용 가능한 할인 횟수 변경

  • 이 고객이 장바구니 변경에 따른 할인 혜택을받습니다.

  • 이 구매 상황에서 쇼핑 기록은 변경되지 않습니다

  • 구매 라인 및 할인 적용에 따라 총 비용이 동적으로 변경됩니다.

  • 초기 신청 후 예를 들어 구매 수량이 변경됨에 따라 할인 출력이 변경 될 수 있습니다.


훌륭하고 완전한 대답 ... 그러나 나는 단지 관심사가 있으며 적어도 대답을 이끌어서는 안되는 가정 섹션이 없어야한다는 것입니다. 전체 아이디어는 패턴이 "편리함"을 정확히 이해하고 잊어 버리는 데 도움이되고, 일반적인 규칙은 계산 방법 및 컨텍스트에서 구현 된 세부 사항 (고객, 장바구니 항목)을 알 필요가 없다는 것입니다. , 주간 시간, 계절 등). 정말 도와
주세요

앞면의 글 머리 기호 및 '가정'섹션은 할인 모델 디자인에 영향을 미치는 문제 자체에 대한 추론입니다. 예를 들어 할인 주문 및 상호 의존성에 대한 나의 가정으로 인해 Chain of Responsibility를 강조하지 못했습니다. @docbrown처럼 복잡한 패턴이 아니라 패턴의 의도에 대해 생각하고 있습니다. 저는 디자인 의도를 반영한 ​​풍부한 지지자입니다.
radarbob

1

논리적으로 할인 모델은 무엇이든 될 수 있으므로 모든 사례를 미리 프로그래밍 할 수 있다고 가정 할 수는 없습니다. 귀하의 질문에 대답하는 사람이 실제로 필요한 것을 완전히 확신 할 수는 없습니다. 그러나 실제 세계에서 발견되는 일반적인 종류의 할인을받는다고 가정하면 ...

큰 문제는 할인이 프로그램 될지 또는 사용자가 입력하도록할지 여부입니다. 위에서 언급 한 바와 같이, 당신은 할 수 결코 그들을 프로그래밍 할 수 없지만 보통의 목표는 오히려 그들 모두를 프로그래밍보다, 그것을 일반적인 경우에 같은 더 많은 데이터 항목을 만들려고하는 것입니다. 이는 프로그래머가 모든 할인을 작성하는 데 사용되는 경우에도 어느 정도 적용됩니다.

Martin Fowler는 회계 시스템에 대한 "게시 규칙"을 구현하는 방법의 일부로 "분석 패턴 : 재사용 가능한 개체 모델"에서 "개별 인스턴스 방법"을 언급하지만 규칙은 사용자와 상당히 비슷해 보입니다. 더 자세하게 설명하지만 저작권이있는 저작물이며

사용자 인터페이스의 경우 상당히 간단한 유스 케이스를 작성하거나 인터프리터 및 쿼리 빌더를 빌드해야합니다. 아마도 간단한 경우를위한 것이고 하나는 더 진보 된 것일 수도 있습니다. 인터프리터를 작성하는 경우 파서 생성기와 비교하여 코드를 작성하는 것이 비교적 간단하고 구문 분석 시간이 느려질 수 있기 때문에 인터프리터 패턴을 사용하는 것이 좋습니다. 파서 생성기를 사용하는 것을 좋아한다면 멈추지 않을 것입니다.

통역사로 모든 ​​것을 시도하지 마십시오. 언젠가는 자신의 언어로 프로그래밍하기 때문에 실제 언어를 사용할 수도 있습니다. 해석 된 언어가 함수를 지원하는 경우 (아마도 함수 호출을 지원해야합니다. 정의하는 것이 모호한 경우) 실제 언어로 코딩 될 수 있습니다. 당신이해야 할 것 보다이 길을 더 멀리 가지 마십시오.

당신이 무엇을하든, 결국 누군가는 프로모션의 영업일 기준 30 일 이내에 구매했는지 여부에 따라 할인을 원할 것입니다. 영업일은 상점의 우편 번호 또는 고객의 전화 번호로 정의 된 지역에 휴일이없는 경우에만 계산됩니다. 우편 번호. 따라서 완벽한 시스템을 미리 설계하지 마십시오. 때로는 새로운 종류의 할인 코드를 작성하여 그에 따라 디자인해야한다고 가정하십시오.


0

유용한 패턴이 있는지 묻는 요점이 있습니까? 어떤 유형의 패턴이 필요한가-구조적 또는 행동 적?

이상적으로, 이것을 위해 소프트웨어를 작성한다면 알고리즘 만 있으면됩니다 . 다음과 같이 총 할인을 계산하는 간단한 기능 :

cart.calculateDiscount(productVector);

이보다 더 필요한 것은 없습니다!

명확히하기 위해 : 나는 많은 규칙이 있음을 이해합니다-그러한 표현의 가장 기본적인 표현은 규칙베이스의 형태 (데이터 속성 및 결과에 대한 할인)의 형식이어야하며 위와 같은 기능은 그것을 계산하기 위해 반복해야합니다. 규칙이 추가되거나 제거되면 코드를 변경하지 말고 규칙 기반을 변경하십시오.

패턴은 서로 다른 객체가 필요한 경우에만 서로의 API에 액세스하거나 작업을 수행하기 위해 통신 해야하는 경우에만 필요합니다.

추신 : 방화벽이 패킷을 처리하고 패킷을 통과 또는 거부 (또는 수정) 할 때 어떤 디자인 패턴을 사용합니까? 대답은 위에서 설명한 것 중 어느 것도 아닙니다!


물론 그 이상이 필요합니다 !!!. 아이디어는 알고리즘이 코드 구현과 밀접하게 연결되어 있지 않다는 것입니다. 시나리오를 확인하여 더 많은 시나리오가 나올 가능성이 높고 어떻게 든 언급 했더라도 실제로 다른 '규칙'에 의존하는 것은 아닙니다. 규칙은 제품 목록에만 의존하지만 실제로는 고객, 시간, 계절 등에 달려 있다고 생각하는 것은 순진합니다. 그나마 방화벽 구현 당신이 선택 알고 있지만, 사람 나는 DO 많은 구조 / 디자인 패턴 확인했습니다
le0diaz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.