Чи існує модель дизайну, яка застосовуватиметься до моделей зі знижками?


35

Чи існують відомі моделі дизайну для реалізації моделей знижок?

Під моделями зі знижками я маю на увазі наступне:

  1. Якщо клієнт купує Продукт X, Продукт Y та Продукт Z, він отримує знижку 10% або 100 доларів США.

  2. Якщо клієнт купує 100 одиниць Продукту X, він отримує знижку в розмірі 15% або 500 доларів

  3. Якщо за останній рік клієнт приніс понад 100 000 доларів США, він отримує рівну 20% знижку

  4. Якщо замовник придбав 2 одиниці Продукту X, він отримує 1 одиницю Продукту X (або Продукту Y) безкоштовно.

  5. ...

Чи є загальна модель, яка може бути застосована для обробки всіх вищезазначених сценаріїв? Я думаю про кілька моделей, але не в змозі натрапити на загальну.


IIRC усі підручники, які я бачив на прикладах із знижками (їх багато), пропонують схему стратегії
gnat

2
@Kanini Це проблема в реальному світі? У такому випадку це система в режимі реального часу чи відстроченого часу? Чи представлені ці правила як двигун правил або значення бази даних? Чи є ієрархічний пошук знижок за пріоритетом? Шаблон стратегії спрацьовує у більшості випадків, але ваші правила повинні враховуватись, щоб вона працювала
Ubermensch

3
Крім того, якщо хтось придбає 2 одиниці Продукту X, один Товар Y і один Продукт Z, отримаєте як 10%, так і додатковий товар X?
Ubermensch

@gnat кілька посилань на деякі з цих навчальних посібників, будь ласка.
user16764

Відповіді:


18

Якщо проблема полягає в тому, що вам потрібно застосувати кілька знижок, за певних обставин, ви можете розглянути схему ланцюжка відповідальності .

У двох словах, ви передаєте інформацію, яку ви хочете обробити, в перший процесор, і він вирішує звідти, чи передавати її наступним процесорам, перш ніж повертати результат.

Таким чином ви можете змінити структуру та послідовність процесорів, не змінюючи коду виклику.


Ланцюг відповідальності - це ще одна хороша. Можливо, навіть поєднується зі стратегією. У випадку, коли можна застосувати лише одну знижку, кожна стратегія пов'язана з іншою. Кожен ланцюжок обчислює свою знижку (якщо клієнт має право), порівнює її з попередньою знижкою та передає дані клієнта, замовлення та знижки в наступний ланцюжок. +1.
Томас Оуенс

1
Лише моя думка, але я вважаю більш ймовірним, що "Ланцюг відповідальності" є надмірним для цієї справи. Простий перелік моделей зі знижками (за потреби, з номером замовлення) повинен це робити. Сам перелік не залежить від замовника та його замовлень, оскільки до всіх клієнтів слід ставитися однаково. "Ланцюг відповідальності" є більш доцільним, коли список дисконтних моделей дуже часто змінюється під час виконання дуже динамічним чином.
Док Браун

11

Мої стратегічні, декораторські та державні моделі виділяються для мене як потенційні вихідні точки. Держава може бути особливо корисною для 2 або 3, оскільки 2 залежить від стану замовлення і 3 залежить від стану замовника протягом певного періоду. Стратегія та декоратор виділяються серед інших, оскільки ви можете використовувати стратегію для впровадження декількох алгоритмів розрахунку ціни на замовлення та декоратора для додавання нових знижок до замовлення.

Однак пам’ятайте, що дизайнерські зразки - це просто моделі. Можливо, не існує жодної схеми, яка застосовується, а скоріше система шаблонів. Також розглядайте можливість внесення змін до описаних моделей, щоб вони краще відповідали вашому рішенню. Краще мати хороший дизайн, ніж примушувати візерунок, коли це не обов'язково допомагає лише заради того, щоб можна було сказати, що ти маєш шаблон.


Це насправді не те, що має намір зробити модель держави, чи не так?
пдр

@pdr Я не бачу, чому ні. Але це залежить від вашої реалізації. Якщо ваш клієнт об'єкт відстежує знижки, залежні від клієнта, то може бути здійснена операція з повернення знижок, на які клієнт має право. Оскільки клієнт купує речі, атрибути змінюються і реалізація цього методу змінюється за допомогою шаблону стану.
Томас Оуенс

1
Хм, я бачу, що ти маєш на увазі. Я думаю, це залежить від того, чи є клієнт напівпостійним об’єктом у додатку, чи просто щось, що живе в базі даних та потребує оновлення. З питання не зрозуміло, так справедливо. +1
пдр

3
З мого досвіду, ці види дісконтування правил бізнесу постійно змінюються непостійними відділами маркетингу / продажу. Існує велика потреба зробити їх керованими даними та користувачами модифікованими, а не повністю керованими кодами. Як це вплине на вибір моделі?
jfrankcarr

@jfrankcarr На мій погляд, це не було б. Я б заповнив значення для наборів елементів, які призводять до знижок, відсотків відключених тощо від якоїсь конфігурації. Сорт динамічно будує переходи мого стану та атрибути моїх декораторів та стратегій.
Томас Оуенс

10

Ну, я б спроектував дисконтну модель як пари "Передумова" та "Знижка", де "Передумова" - це клас із методами

  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ідеї. Замість ітерації колекції знижок кожна знижка дзвонить наступному хлопцеві. Клас "замовлення клієнта" в цьому випадку не містить колекції знижок.

  • Я думаю, що "hmmmm ...." фактор ланцюжка відповідальності полягає в тому, що кожна Знижка має посилання на наступну. Очевидно, що порядок має значення. Що не так. Також концепція КР полягає в тому, що один об'єкт не може обробити запит, тому він передається "до наступного вищого органу". Наша модель інша. Єдине запит - це розрахунок. Кожна знижка робить це. Вихід або ефект можуть бути нульовими, але кожна знижка розраховується. Я інстинктивно схиляюся до вищої реальності.

Припущення

  • Знижки базуються на поточній кошику та / або історії придбань
  • Можуть застосовуватися нульові або більше знижки. Взаємовиключних знижок немає
  • Належний розрахунок не залежить від порядку, в якому застосовуються знижки.

Що змінюється, що залишається тим самим?

  • Знижки дуже різні. Різна кількість і вид параметрів для складання кожного правила.

  • Аргументи кваліфікованих знижок змінюються по мірі зміни кошика для покупок.

  • Кількість змін, доступних знижок

  • Знижки, які цей клієнт визначає за зміни, коли змінюється його кошик.

  • Історія покупок не змінюється в контексті цієї покупки

  • Загальна вартість динамічно змінюється як функція застосовуваних ліній закупівлі та знижок.

  • Після первинного застосування випуск знижки може змінюватися, наприклад, кількість покупки змінюється.


Чудова і повна відповідь ... Але я лише хвилююсь і полягає в тому, що розділ припущень не повинен бути там, принаймні, щоб не вести відповідь. Вся ідея полягає в тому, що модель допомагає точно забезпечити комфорт і забути про "припущення", загальному правилу не потрібно знати, як проводяться обчислення та що використовує будь-яка детальна реалізація з контексту (Клієнт, елементи Корзини , Денний час, сезон тощо). Дійсно допомогти повною мірою
le0diaz

Попередні кулі та розділ "Припущення" - це лише мій "показ вашої роботи" міркувань про саму проблему, яка, звичайно, має перевагу в дизайні дисконтної моделі. Наприклад, мої припущення про порядок виконання знижок та взаємозалежність призводять до того, що я підкреслюю ланцюжок відповідальності. Зауважте, що я думаю про наміри шаблону, а не про складність, як це робить @docbrown. Я прихильний прихильник відображення намірів у дизайні.
radarbob

1

За логікою, модель знижок може бути будь-якою , тому ви не можете припустити, що ви можете запрограмувати всі справи заздалегідь. Також ніхто не може відповісти на ваше запитання, щоб бути повністю впевненим, що вам насправді потрібно. Однак якщо припустити, ви отримуєте звичайні види знижок у реальному світі ...

Велике питання - чи будуть запрограмовані знижки, чи ви хочете, щоб користувачі їх вводили. Як згадувалося вище, ви ніколи не можете їх запрограмувати, але зазвичай мета полягає в тому, щоб спробувати зробити це більш введенням даних, як для звичайних випадків, а не програмувати їх усі. Це стосується певної міри, навіть якщо програмісти використовуються для створення всіх знижок.

Мартін Фаулер згадує "Індивідуальний метод екземпляра" у "Шаблонах аналізу: об'єктні моделі багаторазового використання" як частину того, як реалізувати "Правила розміщення" для облікових систем, але правила здаються досить схожими на ваші. Я детальніше розповім, але це захищені авторським правом та

Для користувальницького інтерфейсу потрібно або придумати випадки використання, які є досить простими, або ж побудувати інтерпретатора та конструктора запитів. Можливо, і те, і інше для простих випадків і ще одне просунуте. Якщо ви все-таки пишете інтерпретатора, це, ймовірно, досить хороший випадок для використання інтерпретаційного шаблону, оскільки його відносно просто кодувати в порівнянні з генератором парсера, і більш повільний час розбору, ймовірно, насправді не має значення. (Якщо вам подобається використовувати генератори парсера, не дозволяйте мені зупиняти вас).

Не намагайтеся все робити з перекладачем - у якийсь момент ви просто програмуєте на своїй власній крихтій мові, тому ви можете також використовувати справжню. Якщо ваша інтерпретована мова підтримує функції (вона, ймовірно, повинна підтримувати їх виклик - визначення їх є сумнівним), вони можуть бути закодовані справжньою мовою. Не йдіть далі цією дорогою, ніж вам доводиться.

Незалежно від того, що ви робите, врешті-решт хтось захоче, щоб знижка ґрунтувалася на тому, чи купували вони протягом 30 робочих днів після просування - де робочі дні рахуються лише в тому випадку, якщо в регіоні не було відпустки, визначеної або поштовим індексом магазину, або клієнтом Поштовий індекс. Тому не намагайтеся заздалегідь розробити ідеальну систему - припускайте, що вам іноді потрібно буде писати код для нових видів знижок та оформляти відповідно.


0

Чи є питання, чи є корисна для цього схема? Який тип шаблону потрібен - структурний чи поведінковий?

В ідеалі, якби я писав програмне забезпечення для цього, все, що потрібно, - це алгоритм . Проста функція, яка обчислює загальну знижку наступним чином:

cart.calculateDiscount(productVector);

Вам більше нічого не потрібно!

Для уточнення: я розумію, що буде багато правил - більшість основних таких представлень має бути у формі бази правил (набір атрибутів даних та результуюча знижка на неї), а така функція, як вище, дозволила б обчислити її. Якщо правила додаються або видаляються, вам не слід змінювати код - просто змініть базу правил.

Шаблон буде потрібен лише в тому випадку, якщо нам потрібні різні об'єкти для доступу до API один одного або спілкування, щоб поставити завдання на місце.

PS: Подумайте про це - коли брандмауер обробляє пакети та передає або відхиляє пакети (або модифікує їх) - який шаблон дизайну він використовує? Відповідь НІКОЛЬНО з вищеописаного!


Звичайно, потрібно більше цього !!!. Ідея полягає в тому, що алгоритм не поєднаний з реалізацією коду. Якщо ви перевіряєте сценарії, велика ймовірність, що з'явиться більше сценаріїв, і ви якось це згадали, він насправді не залежить від того, від чого буде залежати будь-яке інше «Правило». Наївно думати, що правило залежатиме лише від списку товарів, але насправді залежить від замовника, часу, сезону тощо. Не знаєте, яку реалізацію брандмауера ви перевірили, але ті, які я перевіряю, чи мають багато структурних / дизайнерських моделей
le0diaz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.