Шаблон для плагинов - IoC / DI или нет? - PullRequest
4 голосов
/ 27 февраля 2009

Просто очень общий вопрос, который относится не только к этому примеру.

Допустим, у вас есть Интернет-магазин, и вы хотите реализовать ваучеры / подарочные сертификаты, но с ограничениями. Допустим, у вас есть ваучер со скидкой 20%, но он распространяется только на товары, добавленные в течение последних 3 недель, но не на товары, которые были в специальной акции.

Я вижу два способа решить эту проблему: Первый - кодировать ваш магазин, чтобы «изначально» поддерживать все сумасшедшие типы ваучеров. Кажется, это классический способ, но это требует большой работы заранее и очень малой гибкости (в конце концов, вы не можете заранее знать, что вам нужно, и, возможно, Sales может предложить действительно отличную новую акцию, которая требует новых ваучеров - к следующему понедельнику).

Второй способ - это плагин: ваучеры похожи на плагины, и каждый ваучер имеет свой собственный код. Вы передаете корзину покупок в ваучер, а затем сам ваучер проверяет каждый товар, если он применяется, вносит необходимые изменения и возвращает измененную корзину покупок.

Мне просто интересно, что такое шаблон проектирования для случая 2? Это немного похоже на IoC / DI, но опять же не совсем, потому что ваучеры не заменяют какой-либо существующей функциональности. Это больше похоже на набор объектов со специальным интерфейсом (например, IVoucher), а затем на очередь объектов IVoucher, которая перебирается. Существует ли стандартная схема (и лучшая практика) для этих типов «манипуляторов»?

Редактировать: Спасибо за ответы. Чтобы прояснить это немного, Ваучеры (или Манипуляторы - как уже говорилось, речь идет не только об онлайн-магазинах, но и о похожих ситуациях) - это «тяжелые» объекты, то есть в них есть Business Logic. Таким образом, я могу сказать, что Ваучер применяется только в том случае, если Клиент зарегистрировался до 1 января 2008 года, только если клиент заказал по крайней мере 100 долларов США за последние 6 месяцев, применяется только к статьям категории X, которые «складываются» с другими Ваучерами, кроме для предметов, помеченных как уменьшенные и т. д. и т. д. Итак, я больше беспокоился о том, как сохранить чистую структуру, чтобы убедиться, что ваучеры получают все, что им нужно, чтобы проверить, применимы ли они, и чтобы иметь возможность манипулировать корзиной, поэтому я удивился о том, что является стандартом для таких ситуаций, и именно это, по-видимому, делает шаблон посетителя.

Ответы [ 3 ]

7 голосов
/ 27 февраля 2009

Это тот случай, когда вы можете использовать шаблон стратегии вместе с шаблоном vistor для расчета стоимости корзины.

Вистор может посещать каждый товар в корзине, используя разные стратегии (в данном случае, ваучеры на скидку) и используя их для расчета полной стоимости корзины.

Использованные ваучеры можно каким-то образом извлечь из базы данных и довольно просто внедрить в посетителя.

Стратегия ваучера может выглядеть примерно так:

public interface IVoucher
{
    decimal CostOf(CartItem cartItem);
}

По умолчанию будет что-то вроде этого:

public class FullPriceVoucher : IVoucher
{
    public decimal CostOf(CartItem cartItem)
    {
        return cartItem.Cost;   
    }
}

10% скидка будет выглядеть примерно так:

public class TenPercentOffVoucher : IVoucher
{
    public decimal CostOf(CartItem cartItem)
    {
        return cartItem.Cost * 0.9m;   
    }
}

Тогда у вас может быть посетитель для расчета стоимости корзины, такой как:

public class CartValueVisitor
{
    private IVoucher voucher;

    public CartValueVisitor(IVoucher voucher)
    {
        this.voucher = voucher;
    }

    public decimal CostOf(Cart cart)
    {
        return cart.Items.Sum(item => voucher.CostOf(item));
    }
}

Что бы вы использовали как:

var cart = GetACart();

var fullPriceCartValueVisitor = 
        new CartValueVisitor(new FullPriceVoucher());
var tenPercentOffCartValueVisitor = 
        new CartValueVisitor(new TenPercentOffVoucher());

var fullPrice = fullPriceCartValueVisitor.CostOf(cart);
var tenPercentOffPrice = tenPercentOffCartValueVisitor.CostOf(cart);

Это, очевидно, работает только с одним ваучером за раз, но должно дать вам представление об общей структуре.

5 голосов
/ 27 февраля 2009

Предыдущие ответы, предлагающие шаблоны «Посетитель» и «Стратегия», звучат для меня хорошо, хотя Посетитель излишне убивает в типичном случае, когда каждый предмет покупки является объектом того же конкретного класса. Цель Visitor - разрешить динамическую диспетчеризацию для двух (или более) типов объектов - посещаемые объекты являются частью одной иерархии, а посетители - частью другой. Но если меняется только один тип объекта (конкретный тип класса, реализующий IVoucher), то все, что вам нужно - это обычная старая виртуальная диспетчеризация одного типа.

На самом деле я лично не стал бы беспокоиться ни о каком «шаблоне» - ваше собственное описание - это именно то, что нужно: создайте интерфейс, IVoucher, и кучу классов, которые реализуют этот интерфейс. Вам также понадобится фабричный метод, который принимает код ваучера и возвращает объект IVoucher, имеющий соответствующий конкретный тип.

Остерегайтесь некоммутативных ваучеров!

Тот факт, что вы упомянули очередь объектов, реализующих IVoucher, будет выполняться для покупаемых предметов, подразумевает, что можно использовать более одного ваучера. В этом случае вам нужно быть осторожным - применяет ли ваучер A, то ваучер B всегда имеет тот же эффект, что и применение B, а затем A? К сожалению, многие типичные «специальные предложения», по-видимому, не обладают этим свойством (например, если ваучер A дает вам скидку 10 долларов, а ваучер B дает скидку 5%, заказ определенно имеет значение).

Быстрый и грязный выход из этого - назначить каждому ваучеру отдельное числовое значение «приоритета» и всегда применять ваучеры в порядке приоритетов. Чтобы уменьшить вероятность «странных» комбинаций ваучеров, которые могут привести к банкротству, возможно, также целесообразно ограничить комбинации ваучеров некоторым набором разрешенных комбинаций, указанных в вашем коде. (Это может быть так же просто, как список списков кодов ваучеров.)

2 голосов
/ 27 февраля 2009

Может быть, Шаблон посетителя ? Различные типы ваучеров - это посетители, которые посещают корзину и манипулируют ею.

Я не думаю, что МОК является решением здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...