Сегодня я покажу "обратный" пример иллюстрирующий позднее связывание. В одной из своих статей Джоэль Спольски рассматривал интересный пример делегатов. Мне он понравился и мы посмотрим его более расширенную версию.
Итак у нас с вам стоит задача разработать метод шеф-повар, который получает продукт и "рецепт" и на выходе вроде как мы должны получить готовое блюдо.
Начнем с описания ингредиента участвующего в приготовлении:
Т.е. все реальные ингредиенты будут потоками нашего класса Ingredient. Например, мясо может быть описано как нибудь так:abstract class Ingredient
{
}
* This source code was highlighted with Source Code Highlighter.
Как же будет выглядеть метод позволяющий приготовить ингридиент в соответвии с некоторым рецептом? Первый параметр у о будет соответственно Ingredient, а в качестве второго массив делегатов (я специально не использую List, для упрощения написания примера), принимающих все тот же Ingredient, и возвращающих как не странно его-же.class Meat : Ingredient
{
public MeatState State;
public MeatTaste Taste;
public float Temperature;
}
* This source code was highlighted with Source Code Highlighter.
Теперь давайте попробуем что нибудь приготовить:static Ingredient Cook(Ingredient p_ingredient, Func<Ingredient, Ingredient>[] p_recipe)
{
Ingredient result = p_ingredient;
for (int i = 0; i < p_recipe.Length; i++)
{
result = p_recipe[i](result);
}
return result;
}
* This source code was highlighted with Source Code Highlighter.
Запустив приложение, увидим:static void Main(string[] args)
{
// Мясо из холодильника
Meat meat = new Meat { State = MeatState.Сырое, Taste = MeatTaste.Пресное, Temperature = -4 };
// Операции
//Func<Ingredient, Ingredient> defrost =
// Рецепт
Func<Ingredient, Ingredient>[] recipe =
{
// Разморозить
ing => { Meat m = (Meat)ing; m.Temperature = 20; return m;},
// Отбить
ing => { Meat m = (Meat)ing; m.State = MeatState.Отбитое; return m;},
// Посолить
ing => { Meat m = (Meat)ing; m.Taste = MeatTaste.Посоленное; return m;},
// пожарить
ing => { Meat m = (Meat)ing; m.State = MeatState.Жаренное; m.Temperature = 95; return m;},
// Поперчить
ing => { Meat m = (Meat)ing; m.Taste = MeatTaste.Вкусное; return m;}
};
// Запускаем готовку
Console.WriteLine("Мясо до готовки {0} {1}, t={2}", meat.State, meat.Taste, meat.Temperature);
Meat result = (Meat)Cook(meat, recipe);
Console.WriteLine("Мясо до готовки {0} {1}, t={2}", meat.State, meat.Taste, meat.Temperature);
Console.ReadKey();
}
* This source code was highlighted with Source Code Highlighter.
Как видим, наш метод который ничего не знал про мясо и как его готовить получив ингредиент и рецепт приготовил вкусное мясо.
На сегодня наверно, все. Есть еще пара идей по демонстрации позднего связывания на делегатах, но это наверно в другой раз.
Классный пример, здорово :D
ОтветитьУдалить:)
ОтветитьУдалитьЧто то я совсем вчера был не внимателен, столько опечаток... Поправил все, кроме опечатки в листинге, где после готовки говорится "мясо до готовки". Но лень переделывать картинку.