На этом воркшопе будут примеры использования структурных паттернов. Код воркшопа: 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