ООП для ПЛК. Codesys и «Стратегия»
Нашёл в интернете полезный и интересный пост. Сохраняю, может кому пригодится.
Стратегия — это поведенческий паттерн проектирования, который определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.
Вот такое определение мы скопируем и вставим, чтобы начать наше повествование. И уже после прочтения определения закрадывается мысль, а как на ПЛК можно в ООП? По факту легко. И очень много подобных паттернов можно переложить на рельсы промышленного программирования.
Для реализации этого безумства нам потребуется Codesys 3.x ибо он немного, да научился в ООП. Преступим.
РЕАЛИЗАЦИЯ
Что нам предлагают умные статьи в интернетах?
Паттерн Стратегия предлагает определить семейство схожих алгоритмов, которые часто изменяются или расширяются, и вынести их в собственные классы, называемые стратегиями .
Вместо того, чтобы изначальный класс сам выполнял тот или иной алгоритм, он будет играть роль контекста, ссылаясь на одну из стратегий и делегируя ей выполнение работы. Чтобы сменить алгоритм, вам будет достаточно подставить в контекст другой объект-стратегию.
Важно, чтобы все стратегии имели общий интерфейс. Используя этот интерфейс, контекст будет независимым от конкретных классов стратегий. С другой стороны, вы сможете изменять и добавлять новые виды алгоритмов, не трогая код контекста.
Интерфейс
Интерфейс, согласно документации Codesys, — это средство объектно-ориентированного программирования. Объект ITF («Интерфейс») описывает набор прототипов методов и свойств. В этом контексте прототип означает, что методы и свойства содержат только объявления и не содержат реализации.
Это значит, что в интерфейсе мы описываем методы. Даем им имена, перечень входных и выходных данных, но никак не трогаем реализацию.
Создание интерфейса
Для создания интерфейса жмем ПКМ->Добавление объекта->Интерфейс, далее задаем ему имя. У меня это будет «StrategyInt».
Затем добавляем метод. Назовем его GetSTR. Для добавления также правая кнопка мыши и добавить метод интерфейса.
Прописываем там лишь одну выходную переменную.
Описание переменных метода интерфейса.
Теперь, когда мы будем создавать функциональные блоки, наследуемые от этого интерфейса, то в нем мы уже будем иметь метод GetSTR с выходной переменной OUT.
Контекст
Это тот функциональный блок, который и будет у нас вызывать различные «стратегии».
Создаем обычный функциональный блок.
Функциональный блок, который играет роль контекста.
На вход функционального блока мы можем отправить любой объект, который будет унаследован от интерфейса StrategyInt. В реализации мы видим. что при вызове данного функционального блока, мы будем взывать метод GetSTR,а результат возвращать в выходную переменную Result.
Стратегии
Следующий шаг — реализация стратегий. Для начала сделаем две. Они не будет ничем отличаться кроме как возвращать разные значения.
Создаем функциональный блок и наследуем его от нашего интерфейса.
Окно создания функционального блока.
Имя можете указать любое, у меня просто кончилась фантазия.
Я создал два таких блока, которые и будут играть роль наших стратегий.
Созданные стратегии
В каждом есть два метода, реализацию которых необходимо написать.
реализация первой стратегии
реализация второй стратегии.
Да можно напрямую возвращать значения через метод, но я так не хочу.
СБОРКА
А теперь собираем это все вместе.
Сборка всех компонентов.
Я тут немного разбил по шагам. Для реализации нам понадобится. Объект, который играет роль контекста — 1 шт. Наши стратегии. Тут я их включил в блок переменных, но можно и сделать указатель на объект нужной нам стратегии, а уже в коде создать через __NEW.
Ну и переменные Out_1 и Out_2 для наглядности.
Код работаем следующим образом. На первом шаге мы даем на вход MyProc переменной Object нашу стратеги POU_1. Затем происходит вызов контекста и он отрабатывает, записывая результат своей работы в переменную Out_1.
Затем мы даем на вход того же контекста стратегию POU_2, с последующим выводом, результат пишется в переменную Out_2.
Включаем эмуляцию.
Результат выполнения.
Таким образом можно разносить логику работы объектов, которые похожи, но немного отличаются в реализации. Возврат строковой переменой тут просто для примера)
Пост Александра Судалина
Первоисточник статья на ЯндексДзене.