На этом воркшопе будут примеры использования структурных паттернов. Код воркшопа: https://github.com/is-oop-y27/workshop-3
Техническое задание: на основе модели создания статей из второго воркшопа сделать поддержку математических выражений.
Математические выражении могут содержать константы, переменные, бинарные операции (сложение, вычитание, умножение, деление), а также при данных значениях переменных уметь вычисляться.
Заметим, что любое выражение можно представить в виде бинарного дерева.
Сделаем в проекте второго воркшопа папку Expressions, где будет независимая от моделей статей реализация выражений. В ней создадим интерфейс IExpression с двумя методами:
string Format() для преобразования объекта выражения в строкуExpressionEvaluationResult Evaluate(IExpressionEvaluationContext context) для вычисления выраженияДля вычисления выражения сделаем объект контекста, в котором будем производить вычисления.
Контекст IExpressionEvaluationContext содержит в себе имена переменных и их значения.
Внутри контекст вычисления выражения
будет содержать словарь. У контекста сделаем метод, возвращающий резалт-тайп со значением переменной.
Для него же сделаем билдер.
Операнды выражения в нашей модели являются либо константными значениями, либо переменными. Для констант сделаем
класс ConstantExpression, реализующий IExpressionValue, наследующийся от IExpression. У константного значения
сделаем свойство Value
Для VariableExpression, реализующий IExpression, сделаем метод Evalute, который достает значение из словаря контекста
Чтобы применять арифметические операторы к выражениям, сделаем BinaryOperatorExpression, принимающий два IExpression и
IBinaryOperator. Реализации IBinaryOperator будут хранить в себе логику обработки двух выражений. По сути IBinaryOperator является поведенческим паттерном “Стратегия”. При вычислении BinaryOperatorExpression будет пытаться вычислить значения у своих детей; при успехе он применит операцию к полученным значениям.
Теперь сделаем Articles.Extensions для того, чтобы связать модели статей и матвыражений
Сделаем класс ExpressionRenderable - он будет мостом между интерфейсов IRenderable и IExpression. При вызове Render объект будет возвращать текстовое представление выражения.
Также сделаем декоратор StyledExpressionDecorator - он реализует интерфейс IExpression и содержит в себе модификатор для текста, при вызове метода Format он будет возвращать сформатированный текст. Аналогично сделам для интерфейса IExpressionValue