2016-10-26 3 views
2

Это своего рода общий вопрос, позвольте мне сформулировать его в конкретном сценарии. Я кодирую систему ценообразования. В одной руке есть несколько «двигателей», с другой - несколько «инструментов». Я создал иерархии классов для них обоих.Двухсторонний дизайн-схема ООП

Проблема в том, что я хочу реализовать механизм ценообразования. Учитывая конкретный движок И конкретный инструмент, вместе они определяют алгоритм для расчета цены. Было бы неплохо закодировать его в таблице из двух записей. Оба экземпляра содержат важную информацию, ни одна из них не кажется более важной, чем другая. В методах ООП относятся к одному классу, поэтому я не вижу приличного дизайна для решения этой проблемы: метод ценообразования должен быть в классе «Инструменты» или «Двигатели»?

Как бы то ни было, у меня такая же проблема. Предположим, я решил, что это должно быть в двигателях. Затем, внутри методов ценообразования я должен иметь инструкцию «if-then-else», касающуюся каждого возможного инструментария? Это кажется слишком уродливая (и тесная связь!), Особенно, если я буду иметь, чтобы проверить его с чем-то вроде

isinstance(inst, InstrClass1) 

Я могу себе представить, возникают подобные ситуации во многих контекстах. Каков наилучший дизайн-шаблон для решения этих проблем?

перефразировать как пример транспортного средства + Circuit

что у вас есть, с одной стороны, иерархия классов транспортных средств. Есть мотоциклы, автомобили и т. Д. Конкретный объект может быть Yahama Ray, это пример мотоцикла, а также автомобиля.

С другой стороны, у вас есть цепи. И классы LeMans, Jerez, LagunaSeca и т. Д.

Мы хотим, чтобы имитировать характеристики данного автомобиля в данной схеме. Например, предположим, что выход - это время, необходимое транспортному средству для завершения одного круга. Для мотоциклов и автомобилей физика отличается, , поэтому у вас есть разные алгоритмы. Но также предположим, что в некоторых схемах вам необходимо учитывать некоторые факторы , которые в других не имеют значения. Итак, только когда вы знаете все детали автомобиля и схемы, вы можете имитировать. Вы не можете просить схему «имитировать себя» и получить время, а затем попросить также «имитировать себя» и дать вам в другой раз и, наконец, подготовить окончательный ответ с этими двумя.

Надеюсь, это проливает свет на то, что я пытаюсь сделать.

+2

Если речь идет о комбинациях, это должно быть в чем-то, что представляет собой комбинацию. – PeeHaa

ответ

1

Нет универсального ответа на этот вопрос, поскольку решение всегда будет специфичным для домена.

Однако, как правило, если существует логика, которая не подходит ни к одному существующему объекту, тогда вы просто пропускаете дополнительную концепцию, и эта концепция обычно представляется как служба без состояния, но не всегда.

Например, есть скидка 15%, когда Engine1 и Instrument1 покупаются вместе.

Очевидно, что скидка логик не принадлежит ни к одному из Engine1 или Instrument1, но вы, вероятно, есть Order, который содержит оба элемента и порядок может иметь способ применения скидки. Discount s может проверить Order, чтобы узнать, удовлетворена ли их политика применения и может вернуть обратно сумму скидки для определенного заказа.

class Order { 
    ... 

    public void applyApplicableDiscounts(List<Discount> discounts) { 
     for (Discount discount : discounts) { 
      if (discount.isApplicableTo(this)) { 
       this.discounts.add(discount); 
      } 
     } 
    } 

    public Price netPrice() { 
     return sumAllOrderLinePrices(); 
    } 

    public Price totalPrice() { 
     Money discountAmount = sumAllDiscountAmounts(); 

     return netPrice().deduct(discountAmount); 
    } 
} 

class Engine1BoughtWithInstrument1Discount implements Discount { 
    public boolean isApplicableTo(Order order) { 
     return order.containProducts(/*Engine1, Instrument1*/); 
    } 

    public Money amountFor(Order order) { 
     return order.netPrice().percentageOf(15); 
    } 
} 

Теперь, для примера транспортного средства + схемы это то же самое. Вероятно, у вас должно быть состояние Simulation или stateless SimulationService, которое может запускать симуляцию с учетом транспорта, схемы, обучения, законов физики и т. Д. Это может стать очень сложным, но по существу эти различные сотрудники должны позволить компоненту, выполняющему симуляцию, запрашивать их чтобы собрать детали, необходимые для имитации.

К сожалению, я ничего не знаю об этом доменном и физическом законах, но, как очень простой пример (возможно, глупый), служба симуляции может запросить схему, чтобы узнать местность в определенной точке и спросить транспортное средство потому что это поверхность и форма колеса, чтобы знать, сколько будет создано трение.

+0

plalx @ Спасибо, я подумаю об этом, это дает мне отправную точку! – zeycus

0

Мне кажется, вам нужен 3-й тип: цена, которая использует экземпляр Instrument и экземпляр Engine. Класс ценообразования отвечает за расчет цены.

2

Возможно ли иметь калькуляторСервис, который имеет метод, который использует двигатель и инструмент. Он может содержать логику, которая будет консолидировать цену двигателя и цену инструмента. Индивидуальные цены будут поступать от объектов Engine и приборов, поэтому инкапсуляция не будет нарушена.

class CalculatorService { 
    public BigDecimal calculatePrice(Instrument instrument, Engine engine) { 
    def instrumentPrice = instrument.calculatePrice() 
    def enginePrice = engine.calculatePrice() 
    //algorithm to consolidate both prices. 
    return consolidatedPrice 
    } 
} 
+0

Спасибо за ваш ответ, но я думаю, что это не подходит моему примеру. Моя ошибка, может быть, мне следовало бы дать более подробную информацию. Позвольте мне немного изменить пример, к более привычной настройке: «Транспортные средства и схемы». – zeycus

Смежные вопросы