Я действительно не хотел публиковать этот вопрос, но у меня уже несколько дней нет идей. В моем университете мне дали задание использовать шаблоны проектирования для «решения» некоторых задач.
Вот задача, на которой я застрял (перевод):
В киоске есть 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();
}
}
Есть несколько шаблонов проектирования, которые можно использовать, но это зависит от того, как вы подходите к проблеме. Если это один шаг, который изменяет поведение на одном этапе, то это шаблон стратегии, если вы изменяете объект во время создания, то это шаблон фабрики. так что это зависит от вашего подхода
@SimonWilson проблема с фабричным шаблоном заключается в создании нового диспенсера каждый раз, когда я хочу получить коктейль, что, на мой взгляд, не очень хороший способ. Также мне нужно иметь какое-то место, где будут храниться оба «рецепта» коктейлей, и их можно будет добавлять или удалять.
@ Хошани, почему мне здесь не нравится стратегия, потому что каждый раз, когда человек хочет получить коктейльную программу, ему нужно будет назначать новую стратегию. Если мы создаем его каждый раз, это выглядит довольно плохо с точки зрения производительности. Если он уже создан, то это просто ненужная вещь, потому что единственным методом, в котором будет использоваться стратегия, является Dispense, поэтому вы можете просто напрямую использовать то, что вам нужно.
«Плохо с точки зрения производительности» - я ожидаю, что даже посредственный ноутбук 10-летней давности создаст несколько миллионов дозаторов для коктейлей к тому времени, когда остальная часть механизма закончит дозирование фактической жидкости первого. Сохраняйте чувство перспективы
«Плохо с точки зрения производительности», поэтому их называют шаблонами проектирования!
Я бы предложил использовать шаблон Factory Method
. Имейте в виду, что в GoF нет шаблона Factory, только шаблоны Factory Method и Abstract Factory.
Я не дам вам решение, но я предоставлю подробности здесь.
Dispenser
объекта (это ваш реферат Creator
)AlchoholicDispenser
в качестве бетона Creator
и NonAlchoholicDispenser
в качестве другого бетона Creator
. Позже вы также можете создать ChocolateDispenser
и многие другие.if/else
и в зависимости от запрашивающего выберите объект Dispenser
по вашему выбору.Позже вы можете создать Dictionary<ItemType, Dispenser>
функцию serve как таковую: kiosk.Serve(ItemType.NonAlchoholic)
Код будет выглядеть так
public Beverage Serve(ItemType type) {
dispenserDict[type].CreateItem();
}
Вы можете попробовать шаблон
Factory
, возможно, сCocktailDispenserFactory
, который принимает возраст в качестве параметра... он вернетICocktailDispenser
, экземпляр которого на заводе будет соответствующим образом создан в зависимости от возраста. У вас будет 2 реализацииICocktailDispenser
, алкогольная и безалкогольная. В любом случае, удачи с заданием и не переживайте слишком сильно через 2 недели.