Как отделить переключение режимов и команд - PullRequest
1 голос
/ 25 июля 2011

Как отделить режим (обычно выражаемый перечислениями) от его реализации в командах и их взаимосвязи? Является ли это хорошим шаблоном, описывающим слабую связь между переключателем режима (int, enum, string, ...) и его вызовами команд? Я хочу добавить режимы через config, так что это должно быть (динамически) легко расширяемым (без программирования). Я уже знаю шаблон команды (ICommand в C # /. Net). Это может быть словарь команд и связанный с ними номер режима, но как насчет логики переключения?

1 Ответ

2 голосов
/ 27 июля 2011

Можно отделить контекст (переключение дескрипции, параметры) от стратегии для решения запроса (входных данных) и его ответа (выходных данных).

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

public class Strategy<TInput, TOutput>
{
    public Predicate<TInput> Condition { get; private set; }
    public Func<TInput, TOutput> Result { get; private set; }

    public Strategy(Predicate<TInput> condition, Func<TInput, TOutput> result)
    {
        Condition = condition;
        Result = result;
    }

    public TOutput Evaluate(TInput input)
    {
        return Condition(input) ? Result(input) : default(TOutput);
    }
}

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

public class Context<TInput, TOutput>
{
    private List<Strategy<TInput, TOutput>> Strategies { get; set; }

    public Context(params Strategy<TInput, TOutput>[] strategies)
    {
        Strategies = strategies.ToList();
    }

    public TOutput Evaluate(TInput input)
    {
        var result = default(TOutput);
        foreach (var strategy in Strategies)
        {
            result = strategy.Evaluate(input);

            if (!Equals(result, default(TOutput)))
                break;
        }

        return result;
    }
}

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

1.Определите ваши действия (для упрощения это (как видите, у каждого метода есть своя логика и забота):

    private static string Move(string s)
    {
        if (s == "move")
            return "doMove"; // here could be some more action...
        return null;
    }

    private static string Query(string s)
    {
        if (s == "point")
            return "queryPoint"; // here could be some more action...
        return null;
    }

2. Определите условие для запускаоценка (например, CanExecute of ICommand):

    private static bool Condition(string s)
    {
        return !string.IsNullOrEmpty(s); // could eval different states, values
    }

... вы могли бы даже определить больше условий (например, одну функцию оценки условий на стратегию), но мы используем здесь только одно.

3. Создайте объекты стратегии , требуемые контекстом (они символизируют различные пути коммутатора и дают нам результат):

 var navigate = new Strategy<string, string>(Condition, Move);
 var query = new Strategy<string, string>(Condition, Query);

2. Инициализируйте ваш контекст (представляет корпус переключателя со входом):

 var strategies = new List<Strategy<string, string>> {navigate, query};
 var context = new Context<string, string>(strategies.ToArray());

3. Подключите их к коду (например, выполните «переключатель» нажатием кнопки):

    private void ButtonClick(object sender, RoutedEventArgs e)
    {
        var message = context.Evaluate(textBox1.Text);

        if (message != null) MessageBox.Show(message); // display result
    }

... вот и все.

Контекст дает вам правильную стратегию (может выполнять правильные действия или предоставлять «инструменты», необходимые для выполнения некоторых действий (например, ICommand).

...