Вопрос по подходу к реализации паттерна стратегия c#
От: corpse56  
Дата: 05.12.19 17:43
Оценка:
Здравствуйте!
Никак не могу определиться, какой подход лучше применить для реализации паттерна стратегия. (может я не тот паттерн выбрал?)
Задача такая. Есть магазин, который продаёт товары. Каждый товар должен продаваться по своему алгоритму. Было решено применить паттерн стратегия. Получилось два варианта. Какой из них более правильный я не пойму. Я приведу оба примера и опишу что смущает.
Вариант 1. Логику продажи каждого товара инкапсулируем в класс магазина, который наследуем от интерфейса:
using System;                    
public class Program
{
    public static void Main()
    {
        Shop shop = new Shop();
        var a = new A("A");
        shop.Sell(a);
        var b = new B("B");
        shop.Sell(b);
    }
}
interface IShop
{
    void Sell(A a);
    void Sell(B b);
}
class baseClass
{
    public string Name;
}
class A : baseClass
{
    public A(string s)
    {
        this.Name = s;
    }
}
class B : baseClass
{
    public B(string s)
    {
        this.Name = s;
    }    
}
class Shop : IShop
{
    public void Sell(A a)
    {
        Console.WriteLine("sell AAA"+a.Name);
    }
    public void Sell(B b)
    {
        Console.WriteLine("sell BBB"+b.Name);
    }
}

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

Вариант 2. Логику продажи каждого товара икапсулируем в сам товар:
using System;
using System.Collections.Generic;                    
public class Program
{
    public static void Main()
    {
        List<baseClass> list = new List<baseClass> { new A("A"), new B("B"), new B("B"), new A("A") };
        Shop shop = new Shop();
        foreach(baseClass item in list)
        {
            shop.seller = item.seller;
            shop.seller.Sell(item);//это эквивалентно    item.seller.Sell(item);
        }
    }
}

class Shop
{
    public ISellable seller;
}

interface ISellable
{
    void Sell(baseClass a);
}
class baseClass
{
    public string Name;
    public ISellable seller;
}
class A : baseClass
{
    
    public A(string s)
    {
        this.Name = s;
        seller = new SellerA();
    }
    
}
class B : baseClass
{
    public B(string s)
    {
        this.Name = s;
        seller = new SellerB();
    }    
    
}
class SellerA : ISellable
{
    public void Sell(baseClass a)
    {
        Console.WriteLine("sell AAA"+a.Name);
    } 
}
class SellerB : ISellable
{
    public void Sell(baseClass b)
    {
        Console.WriteLine("sell BBB"+b.Name);
    } 
}

Здесь смущает то, что продаёт-то магазин! А не товар сам себя продаёт! shop.seller.Sell(item); === item.seller.Sell(item); Зачем тогда класс магазина вообще нужен? Нет, ну, конечно, я описываю абстрактную ситуацию, и класс магазина описывает ещё полно всякого поведения и параметров. Но в данном конкретном примере получается, что товар продаёт сам себя. И только искусственно если добавить ссылку в магазин на интервейс, то типа будет выглядеть как-будто продаёт магазин. Ещё смущает то, что нужно присваивать каждый раз нужный интерфейс перед продажей. Ну или не присваивать, а сказать товару, чтобы продал сам себя, а он ещё и ссылку на себя получает.

Я понимаю, что вопрос тот ещё. Но может всё-таки я где-то блуждаю не там?
Что можно сказать про "магазин"? Типов товаров будет немного, всего около 7-8. Ещё магазин должен будет каждый товар уметь принимать на склад, принимать бракованый товар назад, отсылать товар в ремонт и т.д.
Даже этот список дейтсвий помножить на 7 получится ~30 методов в IShop для первого примера. А для второго примера получится, что не магазин управляет товаром, а товар управляет сам собой ...
Лично мне больше нравится второй пример, если б не то обстоятельство, что товар сам себя "обслуживает". Или это нормально? Посоветуйте, пожалуйста, что-нибудь! Может другой паттерн или где-то я ошибся в реализации?
использую c#
Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.