Какой шаблон проектирования подходит для использования?

Я действительно не хотел публиковать этот вопрос, но у меня уже несколько дней нет идей. В моем университете мне дали задание использовать шаблоны проектирования для «решения» некоторых задач.

Вот задача, на которой я застрял (перевод):

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

Я уже сделал 2 решения, но ни одно из них не имеет шаблонов проектирования. Я думал о порождающих паттернах, но, судя по примерам их использования, не думаю, что это хороший выбор. Также думал о стратегии, посреднике, цепочке ответственности, фасаде и мостике, но, как мне показалось, и здесь это не подходит.

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

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

Какой шаблон проектирования я могу использовать в моей ситуации?

Вот моя последняя попытка

public class Kiosk
{
    private readonly Dispenser _alcoholicDispenser = new Dispenser(), _nonAlcoholicDispenser = new Dispenser();

    public void AddCocktail(string name, CocktailRecipe alcoholicRecipe, CocktailRecipe nonAlcoholicRecipe)
    {
        _alcoholicDispenser.AddCocktail(new Cocktail(name, true, alcoholicRecipe));
        _nonAlcoholicDispenser.AddCocktail(new Cocktail(name, false, nonAlcoholicRecipe));
    }

    public bool RemoveCocktail(string name)
    {
        if (!_alcoholicDispenser.RemoveCocktail(name)) 
            return false;

        _nonAlcoholicDispenser.RemoveCocktail(name);
        return true;
    }

    public Cocktail GetCocktail(Person person, string cocktailName)
    {
        if (person.Age < 18) 
            return _nonAlcoholicDispenser.Dispence(cocktailName);
        else 
            return _alcoholicDispenser.Dispence(cocktailName);
    }
}

public class Dispenser
{
    private readonly Dictionary<string, Cocktail> _cocktails = new Dictionary<string, Cocktail>();

    public void AddCocktail(Cocktail cocktail)
    {
        _cocktails.Add(cocktail.Name, cocktail);
    }

    public bool RemoveCocktail(string cocktailName)
    {
        return _cocktails.Remove(cocktailName);
    }

    public Cocktail Dispence(string cocktailName)
    {
        return _cocktails[cocktailName];
    }
}

public class Cocktail
{
    public string Name { get; set; }
    public bool Alcoholic { get; set; }
    public CocktailRecipe Recipe { get; set; }

    public Cocktail(string name, bool alcoholic, CocktailRecipe recipe)
    {
        Name = name;
        Alcoholic = alcoholic;
        Recipe = recipe;
    }

    public override string ToString()
    {
        string res = "Name:" + Name + "(" + (Alcoholic ? "alcoholic" : "non-alcoholic") + ")";
        return res;
    }
}

public class CocktailRecipe
{
    public List<Ingredient> Ingredients { get; set; }
}

public class Ingredient
{
    public string Name { get; set; }
    public double Volume { get; set; }

    public Ingredient(string name, double volume)
    {
        Name = name;
        Volume = volume;
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var kiosk = new Kiosk();

        kiosk.AddCocktail("Mojito", new CocktailRecipe(), new CocktailRecipe());

        var majorPerson = new Person("Tom", 20);
        var minorPerson = new Person("Jimmy", 17);

        Console.WriteLine(kiosk.GetCocktail(majorPerson, "Mojito"));
        Console.WriteLine(kiosk.GetCocktail(minorPerson, "Mojito"));

        Console.ReadKey();
    }
}

Вы можете попробовать шаблон Factory, возможно, с CocktailDispenserFactory, который принимает возраст в качестве параметра... он вернет ICocktailDispenser, экземпляр которого на заводе будет соответствующим образом создан в зависимости от возраста. У вас будет 2 реализации ICocktailDispenser, алкогольная и безалкогольная. В любом случае, удачи с заданием и не переживайте слишком сильно через 2 недели.

Simon Wilson 20.12.2020 14:10

Есть несколько шаблонов проектирования, которые можно использовать, но это зависит от того, как вы подходите к проблеме. Если это один шаг, который изменяет поведение на одном этапе, то это шаблон стратегии, если вы изменяете объект во время создания, то это шаблон фабрики. так что это зависит от вашего подхода

Hoshani 20.12.2020 14:12

@SimonWilson проблема с фабричным шаблоном заключается в создании нового диспенсера каждый раз, когда я хочу получить коктейль, что, на мой взгляд, не очень хороший способ. Также мне нужно иметь какое-то место, где будут храниться оба «рецепта» коктейлей, и их можно будет добавлять или удалять.

wmdanor 20.12.2020 14:21

@ Хошани, почему мне здесь не нравится стратегия, потому что каждый раз, когда человек хочет получить коктейльную программу, ему нужно будет назначать новую стратегию. Если мы создаем его каждый раз, это выглядит довольно плохо с точки зрения производительности. Если он уже создан, то это просто ненужная вещь, потому что единственным методом, в котором будет использоваться стратегия, является Dispense, поэтому вы можете просто напрямую использовать то, что вам нужно.

wmdanor 20.12.2020 14:26

«Плохо с точки зрения производительности» - я ожидаю, что даже посредственный ноутбук 10-летней давности создаст несколько миллионов дозаторов для коктейлей к тому времени, когда остальная часть механизма закончит дозирование фактической жидкости первого. Сохраняйте чувство перспективы

Caius Jard 20.12.2020 14:43

«Плохо с точки зрения производительности», поэтому их называют шаблонами проектирования!

Hoshani 21.12.2020 14:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
413
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я бы предложил использовать шаблон Factory Method. Имейте в виду, что в GoF нет шаблона Factory, только шаблоны Factory Method и Abstract Factory.

Я не дам вам решение, но я предоставлю подробности здесь.

  1. В вашем элементе киоска вам нужно создать два частных Dispenser объекта (это ваш реферат Creator)
  2. Создайте AlchoholicDispenser в качестве бетона Creator и NonAlchoholicDispenser в качестве другого бетона Creator. Позже вы также можете создать ChocolateDispenser и многие другие.
  3. Внутри своего киоска создайте пункт if/else и в зависимости от запрашивающего выберите объект Dispenser по вашему выбору.

Позже вы можете создать Dictionary<ItemType, Dispenser> функцию serve как таковую: kiosk.Serve(ItemType.NonAlchoholic)

Код будет выглядеть так

public Beverage Serve(ItemType type) {
    dispenserDict[type].CreateItem();
}

Другие вопросы по теме