Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Сильный искусственный интеллект и объектно-ориентированное программирование синтез парадигм
.pdf
наличествует базовый родительский ПК, представленный аб-
страктным классом, и дочерние компоненты этого абстрактного класса. Само собой разумеется, что данные компоненты
связаны наследственностью.
Значимость паттерна в контексте разработки систем
сильного ИИ. «Шаблонный метод» представляет немалый инте-
рес для сферы разработки систем сильного ИИ. Конечно, является понятным, что на одном-единственном паттерне, каким бы
именно он ни был, вряд ли удастся сформировать технотропное
сознание – те абстракции, которые нами выявляются на основе
паттернов ООП, будут функционировать в некой комбинации.
Вот и «Шаблонный метод», точнее те абстракции, которые в него имплицитно встроены, также будут скооперированы с некоторыми иными. Однако же в самом по себе «Шаблонном методе» также наличествует нечто ценное, а именно – незыблемость
структуры реализации алгоритма. Т. е., каким бы образом ни
были переопределены «на местах» абстрактные методы, шаблонный метод (как элемент паттерна) останется самим собой
и будет на своем месте делать то, что должен. Собственно говоря, здесь речь идет также о качественных преобразованиях.
К примеру, как мы уже ранее постулировали, человек способен очень сильно трансформироваться как внешне, так и внутренне, но тем не менее человеком быть он от этого не перестанет. Нельзя будет посмотреть на него и начать утверждать, что
перед нами не человек, а какое-то другое существо. Это означает, что у человека наличествует некая абстрактная основа, незыблемость которой прочно удерживает его в рамках классовой
(в контексте ООП) принадлежности. Таким образом (говоря скорее экзистенциально), у человека наличествует нечто, позволяющее ему быть и оставаться человеком. Формальнее – у человека
есть некие абстрактные характеристики, ответственность которых заключается в том, чтобы человек не был способен претерпеть преобразования такого уровня, который кардинально преобразует его природу.
Собственно говоря, нечто подобное, какой-то схожий механизм, некие чрезвычайно «прочные» абстракции, те самые, ко-
211

торые не позволяют преодолевать рамки класса, которые не
позволяют быть способным на качественное преобразование
с по явлением новых, эмерджентных свойств, являют собой краеугольный камень на пути создания системы сильного ИИ. И в работе с такого рода абстрактными свойствами мы также видим
как минимум два этапа: на первом необходимо заставить систему преодолеть абстрактные ограничения подобного толка с тем,
чтобы выйти на уровень наличия технотропного сознания; на
втором же мы считаем целесообразным непосредственное взаимодействие интеллектуальной системы с определенными абстрактными аспектами самой себя для их осознания и повторного использования в соответствии со своими предпочтениями.
И в контексте реализации данных этапов и способны помочь абстрактные аспекты паттерна «Шаблонный метод».
12.10. Поведенческий паттерн «Посредник»
Идентификатор. Посредник (Mediator).
Классические элементы. Посредник, конкретный посредник,
коллеги.
Назначение. Как указывается в Design patterns, «Посредник»
«определяет объект, инкапсулирующий способ взаимодействия
множества объектов. Посредник обеспечивает слабую связанность системы, избавляя объекты от необходимости явно ссылаться друг на друга…» [114, с. 263]. Под «связанностью» в данном
случае, конечно, подразумевается зацепление – про путаницу
с данными понятиями мы уже говорили ранее. Паттерн «Посредник» представляет собой ПК, предназначенный для, как понятно из названия, осуществления посредничества между другими ПК.
Проблема. В рамках некоторой программной системы наличествует определенное количество ПК, которые некоторым образом связаны друг с другом. Функционирование каждого из
этих компонентов зависит от функционирования некоторого количества других компонентов. В самом худшем случае функционирование каждого из компонентов подобной системы зависит
212

сразу от всех других компонентов этой системы. Как следствие
этого, мы не можем безопасно трансформировать ни один из
компонентов системы, так как рискуем нарушить функционирование системы в целом. Также мы совершенно лишены возможности повторно использовать какой-либо из этих компонентов,
так как будем вынуждены использовать всю систему сразу. Понятно, что пример несколько утрирован, но тем не менее перед
нами, по сути, худший случай нарушения фундаментального
принципа слабого зацепления. Само собой разумеется, что подобную систему необходимо существенно трансформировать.
Это можно осуществить при помощи паттерна «Посредник».
Концептуальное решение. В противовес организации системы, подобной вышеприведенной, мы формируем систему в соответствии с возможностями паттерна «Посредник». Опять же,
у нас имеется некоторая система с определенным количеством
ПК. Успешность функционирования одного отдельно взятого
компонента все так же зависит от некоторых других компонентов. Только в данном случае он уже не знает, от каких именно,
и никак с ними напрямую не связан, а они – компоненты, от которых зависит его функционирование, – также не знают, какой
же компонент от них зависит (так как он, в сущности, уже и не
зависит). Вся связь в рамках подобной системы осуществляется
через специфический ПК (конкретный посредник), который осу-
ществляет всю медиацию в системе. Конечно, при большой системе мы бы воздержались от того, чтобы в буквальном смысле
нагружать один-единственный ПК ответственностью за функционирование всей системы. Мы бы скорее определили базовый
ПК (посредник), в котором, в свою очередь, определили бы общий интерфейс и функционал всех дочерних подкомпонентов.
Это бы позволило создать в рамках системы некоторое количество компонентов-медиаторов, ответственных за осуществление
связи между различными компонентами (коллегами) системы.
Таким образом, в рамках системы мы получаем большое количество ПК, связанных исключительно с посредниками, т. е. прямой связи между компонентами, которые не являются посредниками, не установлено. Посредник же, в свою очередь, сам не
213

удовлетворяет поступающие к нему от компонентов системы
запросы, а подбирает наиболее подходящие из доступных ему
ПК. Подобранный компонент удовлетворяет входящий запрос
и пересылает результат посреднику, который транслирует этот
результат тому компоненту, который посылал запрос. Теперь при
желании добавить в такую систему новый компонент нам просто нужно подключить его к соответствующему посреднику.
Также при желании повторно использовать ПК в некотором ином
контексте у нас не должно возникнуть проблем, так как все компоненты, не являющиеся посредниками, связаны только с посредниками. Т. е. мы можем взять копию ПК и поместить ее
в другой контекст, просто привязав к тому посреднику, который
за тот контекст ответственен. Соответственно, после реализации паттерна система выглядит и функционирует совершенно
иначе.
Предполагаемые результаты и преимущества. Соблюдение фундаментального принципа слабого зацепления со всеми
практическими выгодами, получаемыми из этого. Формирование эластичной, податливой к изменениям и добавлению нового
функционала системы. Реализация возможности повторного использования ПК. Унификация способов взаимодействия между
ПК системы.
Гипотетический пример реализации паттерна. Примеров реализации паттерна в макромире огромное множество:
колл-центры, логистические центры, любые диспетчеры и связующие звенья. Пример реализации паттерна в контексте функционального программирования нами также уже ранее приводился. Однако позволим себе еще один, возможно несколько
грубоватый и чересчур приближенный, но тем не менее пример.
Представим себе некоторое предприятие, в котором наличествует два цеха по производству чего-либо (не важно, чего именно).
И отличается данное предприятие одной интересной особенностью. А именно – каждый инструмент на предприятии представлен в единственном экземпляре и находится то в одном
цеху, то в другом. Каждому рабочему данного предприятия для
получения необходимого ему в данный момент инструмента
214

в случае отсутствия оного в его собственном цеху приходится
идти в дру гой цех и там искать, у кого же на рабочем месте сейчас находится искомый инструмент. Так как подобное сильно
снижает производительность и выработку предприятия в том
плане, что слишком много времени тратится на поиск инструмента и рабочие постоянно ругаются между собой по поводу взятых
без спроса инструментов, было постановлено как-то решать эту
проблему. И так как план закупки дополнительного оборудования
начальству отчего-то не понравился, было принято решение –
нанять специального менеджера по локализации инструментария. Этот человек сидит в проходе между двумя цехами, и к нему адресованы все запросы по быстрому поиску инструментов
в соседнем цеху. Теперь рабочим нет необходимости тратить время на поиски и покидать рабочее место, а также никто никогда
не знает, кто именно запросил инструмент в этот раз и откуда
именно его сейчас принесли. Примерно для этих же целей и применяется паттерн «Посредник».
Осмысление структуры паттерна. Данный паттерн отличается очень простой структурой с довольно явными и однозначными связями. Посредник и конкретный посредник связаны
отношениями наследования, что само по себе понятно, так как
конкретный посредник является подклассом класса посредник.
А вот коллеги связаны с конкретным посредником по типу композиции, так как они не смоги бы без него эффективно функционировать.
Значимость паттерна в контексте разработки систем
сильного ИИ. В контексте разработки систем сильного ИИ дан-
ный паттерн имеет весьма интересную значимость. И это потому
что, вообще говоря, практически буквальным примером реализации подобного паттерна на субстрате интеллектуальных систем является человеческий мозг. Именно мозг обрабатывает
поступающие от различных систем организма входные сигналы
(запросы) и посылает в ответ сигналы, соответственно, выходные
(ответы). Таким образом, мозг осуществляет действительную
медиацию сложной распределенной системы. Каким именно образом он это делает – до сих пор неизвестно, так как имеются
только лишь гипотезы. В мире разработки программного обе-
215

спечения также есть интересные примеры подобного рода. А именно – системы оркестрации, допустим Kubernetes, как одна из
наиболее известных. Системы эти занимаются примерно тем же,
чем человеческий мозг, – осуществляют координацию и менеджмент сложных программных систем. В Kubernetes, к примеру,
наличествует даже такой компонент, как ControlPlan/MasterNode, который так и определяется – мозг Kubernetes. Мы хотим
показать, что роль «Посредника» очень сложно переоценить.
Однако какая же именно абстрактная данность смогла бы играть
подобную роль в системе сильного ИИ – вопрос, который до сих
пор открыт. И это, к слову, один из ключевых вопросов и одновременно одна из наиболее важных задач в контексте построения систем сильного ИИ.
В связи с вышесказанным нам представляется продуктивным попробовать следующее, что вполне соответствует общей
тенденции нашего подхода к разработке интеллектуальных систем подобного уровня. А именно: изначально не определять никакой ПК в качестве посредника между прочими компонентами,
а оставить все компоненты примерно на одном уровне абстракции, в соответствии с организационным принципом ООП SLAP.
Предполагается, что центральный узел должен сформироваться
в процессе развития системы путем самоорганизации, а не быть
жестко зафиксирован с самого начала. И вообще, само наличие
даже такого важного компонента, как центральный узел (мозг
у человека), не обязательно, а опционально, так как возможно,
что система сильного ИИ предпочтет вариант децентрализованной структуры с множеством значимых узлов. Также может
быть и такое, что система предпочтет структуру, в которой она
вся целиком являет собой центральный узел. Какая именно из
этих возможностей будет реализована системой ИИ на практике, покажет только сама практика.
12.11. Поведенческий паттерн «Посетитель»
Идентификатор. Посетитель (Visitor).
Классические элементы. Посетитель, конкретный посети-
тель, элемент, конкретный элемент, структура объектов.
216

Назначение. Как указывается в Design patterns, данный паттерн «абстрагирует метод, позволяющий иметь заранее неопределенное число видов анализа структур глифов без изменения
самих классов глифов» [114, с. 87]. Еще одна полезная особенность «Посетителя» состоит в том, что его «можно применять
не только к таким агрегатам, как наши структуры глифов, но
и к любым структурам, состоящим из объектов. Сюда входят
множества, списки и даже направленные циклические графы»
[114, с. 87]. Назначением паттерна «Посетитель» является посещение некоторой структуры данных, состоящей из определенных элементов, для того, чтобы осуществлять над ними некоторую операцию, не изменяя при этом те элементы структуры
данных, которые им непосредственно посещаются.
Проблема. У нас есть структуры данных, состоящие из определенного количества ПК, каждый из которых относится к некоторому классу, которых также некоторое количество, и, в свою
очередь, каждый из которых определил для своих подклассов
некоторые характерные особенности (поля-значения и методы).
Нам бы хотелось посетить эту структуру данных, т. е., по сути,
пробежаться по ней и выполнить над каждым ее элементом
определенную операцию. Мы можем просто изменить каждый
из классов, к которому принадлежит некоторое количество элементов структуры, реализовав в самих классах ту операцию, которую мы хотим осуществить, а затем просто пробежаться по
структуре данных, вызывая эту операцию поочередно для каждого элемента этой самой структуры. Сложность осуществления этого варианта развития событий находится в прямой зависимости от количества возможных классов элементов структуры
данных. С другой стороны, мы могли бы при изначальном проектировании системы создать один базовый класс, определить
в нем интересующую нас операцию, а затем все прочие классы
реализовать как подклассы этого базового класса, содержащие
в себе по умолчанию возможность осуществления нужной нам
операции. Но мы бы смогли это осуществить только в том случае, если бы заранее, еще до проектирования системы, знали, какую конкретно операцию нам необходимо осуществить. Однако
217

в контексте нашей системы мы не только заранее не знаем, что
именно за операцию нам понадобится осуществлять, но также
знаем, что, возможно, через некоторое время нам понадобится
осуществить какую-либо еще операцию над группой элементов
структуры данных, а далее, возможно, еще и еще. Все, что нам
известно, – это то, что нечто подобное, возможно, понадобится,
но это не точно. Это значит, что второй вариант не подходит
точно. Но ввиду того, что каждый раз при возникновении потребности осуществить некоторую операцию над определенными элементами нам понадобится «руками» трансформировать
структуру каждого из классов этих элементов, первый вариант
также отметается. Но дело не только в сложности внесения изменений. Мы также, согласно одному из принципов SOLID,
принципу разделения интерфейса, не имеем права излишне перегружать ПК методами, которые не являются необходимыми
для успешного осуществления компонентами их основной деятельности, потому что таким образом нарушится фундаментальный принцип сильной связности и еще один из принципов
SOLID – принцип единственной ответственности. В общем,
видно, что ситуация у нас достаточно сложная и проблема возникла серьезная. Но нам все же очень нужно осуществить необходимую операцию над элементами структуры данных. И тут
на помощь приходит поведенческий паттерн «Посетитель».
Концептуальное решение. Как говорилось выше, все, что
нам известно при проектировании некоторой системы, – это то,
что, возможно, при функционировании этой системы нам в дальнейшем может понадобиться от каждого класса какой-либо дополнительный, помимо его основного, функционал, о котором
мы на данный момент ничего не подозреваем. В таком случае
мы можем при определении каждого класса (элемента) данной
системы дополнительно заложить в него единственный метод
доступа к организации этого элемента. Конечно, мы могли бы
вместо этого, как уже тоже говорилось выше, создать просто
один базовый класс с единственным методом – методом доступа
к экземплярам класса, а затем уже все остальные классы наследовать от этого базового класса, реализуя его подклассы. В лю-
218

бом случае суть теперь не меняется и настолько конкретные детали реализации не играют значимой роли в контексте паттерна
«Посетитель». Таким образом, теперь у нас есть система с некоторым количеством классов (элементов), в каждом из которых
реализован метод доступа к экземплярам этого класса. Далее
формируются сами экземпляры класса (конкретные элементы) ,
и затем они оформляются в некоторые организованности наподобие структур данных (структура объектов). И теперь настает
момент, когда мы хотим осуществить некоторую операцию или
некоторое их количество над ПК какой-либо структуры данных.
Для начала мы определяем базовый класс (посетитель), в кото-
ром реализуем необходимые нам операции, специфика которых
зависит от класса, к которому мы будем их применять. Затем мы
по необходимости можем реализовать подклассы (конкретные
посетители) этого базового класса, в каждом из которых можем
дополнить некоторый функционал. Специфика этого функционала уже вариабельна. Теперь при посещении некоторой структуры данных с целью совершить определенную операцию над
ее элементами мы для каждого элемента вызываем его метод
доступа. Элемент в ответ на вызов этого метода возвращает посетителю (как правило) самого себя. И теперь, после определения типа этого элемента, мы наконец-то можем в соответствии
со всеми правилами осуществить нужную нам операцию.
Предполагаемые результаты и преимущества. Предполагаемыми итогами правильного применения паттерна являются
следующие. Соблюдение фундаментального принципа сильной
связности ПК, соблюдение принципов единственной ответственности и разделения интерфейса. Эластичность системы в плане
легкого и удобного добавления к ней новой функциональности.
Полиморфизм посетителя в плане способности эффективно работать с разными классами. Эксплицитная организация программной системы.
Гипотетический пример реализации паттерна. Как ни
странно, но для поведенческого паттерна «Посетитель» полностью
адекватный пример из мира, который не заключается в контексте
разработки программного обеспечения, достаточно непросто
219

подобрать. Часто приводятся примеры с различным инструментарием для различных целей, например с разными ключами для
разных замков и т. д. Но это далеко не в полной мере отражает
довольно сложную суть данного паттерна. Однако по-настоящему хорошие примеры все же наличествуют.
В качестве одного их хороших вариантов можно привести
деятельность ферментов. Ферменты, если несколько абстрагировать их суть, являют собой узкоспециализированные вещества,
которые ответственны за трансформацию некоторого содержимого в иное содержимое. Они катализируют данные реакции
и ускоряют их, по сравнению с естественным ходом событий, во
много раз. Обычно сопоставление фермента с некоторым содержимым осуществляется по принципу «ключ – замок» (сразу ассоциации с key – value), и в том случае, если «ключ» конкретного
фермента подходит к «замку» некоторого вещества, то фермент
способен начать оказывать свойственное себе влияние на вещество, соответствующим образом трансформируя его. Надо обратить внимание на то, что в самом веществе не определена в качестве необходимой операция ускоренного преобразования во
что-либо иное. Определена просто таковая возможность, которая
находит свое воплощение в «замке», которым способен воспользоваться фермент. Фермент также обладает некоторой специализацией, которая резюмируется в наличии у него конкретного
и специфического «ключа». По сути, при помощи этого «ключа»
он фильтрует типы данных и подбирает те, над которыми способен совершить определенную операцию, необходимость выполнения которой заложена в его сущность. Здесь можно даже дополнить, что в самом базовом ферменте (платоновский эйдос) не
определены все конкретные ключи и возможные операции – они
там всего лишь объявлены. Так что данный пример также соответствует и поведенческому паттерну «Шаблонный метод».
В любом случае мы по итогу имеем следующую ситуацию.
У нас имеется некоторое количество компонентов, над которыми
может быть осуществлена некая нужная нам операция, и также
наличествует определенная группа компонентов, которые способны такую операцию осуществить. В компонентах первой
220
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
