Ревью #2 - Spring. Виды бинов Область видимости бинов (scope)
Скачать 39.29 Kb.
|
Что такое бин? Bean в Spring — это объекты, образующие основу приложения и управляемые контейнером (контейнер = интерфейсы и абстр. классы) Spring IoC. Бином является почти все в Spring - сервисы, контроллеры, репозитории, по сути все приложение состоит из набора бинов, в которых описывается бизнес-логика. @Bean - аннотация Spring Framework, она используется над методом для указания того, что данный метод создает, настраивает и инициализирует новый объект, управляемый Spring IoC контейнером. Такие методы можно использовать как в классах с аннотацией @Configuration, так и в классах с аннотацией @Component (или её наследниках). После создания бина операторы new нам не понадобятся, мы будем работать в классе-бине с его полями-бинами так, будто они уже инициированы (только с теми полями, которые сконфигурированы как бины. Остальные инициализируются как обычно, в том числе с помощью оператора new.) Виды бинов? Область видимости бинов (scope): 1.Singleton - является дефолтным scope. В контейнере будет создан только один бин, и все запросы на него будут возвращать один и тот же бин (закэшированный экземпляр). Потокобезопасный, создается сразу при сканировании. Singleton bean можно внедрять в любой другой бин. В сам singleton можно внедрить только prototype или singleton. 2.Prototype - создается каждый раз, когда он запрашивается. Spring не вызывает метод destroy(). Spring не берет на себя контроль полного жизненного цикла бина и не хранит такие бины в своём контейнере, а отдаёт их клиенту и больше о них не заботится (в отличие от singleton-бинов). Не потокобезопасный, создается только после запроса, может быть зависимостью для любого бина. Внедрять можно только prototype или singleton. не отработает предестрой 3.Request - создается новый экземпляр для каждого HTTP-запроса. Таким образом, если сервер в настоящее время обрабатывает 50 запросов, тогда контейнер может иметь не более 50 бинов, по одному для каждого HTTP-запроса. Экземпляры уничтожаются, как только HTTP-запрос завершен. 4.Session - создается в одном экземпляре для одной HTTP-сессии. Все HTTP-запросы в пределах времени жизни одной сессии будут иметь доступ к одному и тому же бину. 5.Application - создается в одном экземпляре для жизненного цикла ServletContext (ServletContext живет и функционирует в пределах процесса сервера и может получать информацию о своем окружении). Виден как атрибут ServletContext. 6.Websocket - создается в одном экземпляре для определенного сеанса WebSocket (тип протокола связи). Один и тот же бин возвращается всякий раз, когда к нему обращаются в течение всего сеанса WebSocket. Виды бинов: 1. Entity Bean – бин, цель которого - хранить данные. В логику такого бина встроен механизм сохранения себя и своих полей в базу данных. Такой объект может быть уничтожен, а потом воссоздан из базы заново. Но кроме хранения данных у него нет никакой логики. 2.Session Bean – функциональный бин. У каждого Session Bean есть своя функция. Такие бины работают с другими объектам и бинами, а не со своими данными. Делится на две категории. -Stateless Session Bean – не хранит во внутренних переменных важных данных, нужных для его работы. Такой бин можно уничтожить, а затем заново создать, и он будет выполнять свою функцию, как и раньше. -Statefull Session Bean – хранит у себя внутри данные, которые использует при работе. Если мы вызываем методы этого бина, то в каждом следующем вызове он может использовать часть данных, переданных ему в предыдущих Чем бин отличается от POJO-класса? POJO (англ. Plain Old Java Object) - простой Java-объект, не унаследованный от какого-то специфического объекта и не реализующий никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели. Spring Bean — это объект, управляемый Spring. В частности, это объект, который создается, настраивается и иным образом управляется контейнером Spring Framework. Spring Bean определяются в файлах конфигурации Spring или при помощи @аннотаций, создаются контейнерами Spring, а затем внедряются в приложения. Различия: 1. Все JavaBeans - POJO, но не все POJO являются JavaBeans. 2. Бины должны реализовывать интерфейс Serializable. Тем не менее, некоторые POJO, которые не реализуют интерфейс Serializable, называются POJO, потому что Serializable - маркерный интерфейс и не несет большой нагрузки. 3. Bean поля должны быть приватными. Это необходимо для обеспечения полного контроля над полями. 4. Bean имеют конструктор по умолчанию 5. К полям Bean обращаются только через геттеры-сеттеры. Что такое Inversion of Control и как Spring реализует этот принцип? IoC (Inversion of Control) - инверсия управления. Это принцип в разработке, при котором управление объектами или частями программы передается контейнеру или фреймворку (Spring’y). Процессом выполнения кода/программы управляет фреймворк, мы передали ему контроль (тем самым “инверсируя управление”). Программирование без фреймворков - наш код обращается к библиотекам, IoC - фреймворк обращается к нашему коду (используя абстракции и свое поведение, рефлексию) Преимущества этой архитектуры: отделение выполнения задачи от ее реализации; легкое переключение между различными реализациями; большая модульность программы; более легкое тестирование программы путем изоляции компонента или проверки его зависимостей и обеспечения взаимодействия компонентов через контракты. Вместо ручного внедрения зависимостей, фреймворк забирает ответственность за это посредством контейнера, который отвечает за управление жизненным циклом объекта (бина): Spring создает объекты (бины), вызывает методы инициализации и конфигурирует объекты путем связывания их между собой. Конфигурирование контейнера осуществляется путём внедрения @аннотаций или XML-файлов. Объекты могут быть получены одним из двух способов: Dependency Lookup (поиск зависимости) - вызывающий объект запрашивает у объекта-контейнера экземпляр объекта с определенным именем или определенного типа. Dependency Injection (внедрение зависимости) - контейнер передает экземпляры объектов по их имени другим объектам с помощью конструктора, свойства или фабричного метода (инициализация объекта через публичный статический метод, называемый фабричным методом). Для чего существует такое количество ApplicationContext? ApplicationContext — это главный интерфейс в Spring-приложении, который предоставляет информацию о конфигурации приложения. Так же, как BeanFactory, ApplicationContext (наследуя BeanFactory и расширяя функционал для enterprise приложений) загружает бины, связывает и конфигурирует их определённым образом. Но, кроме этого, ApplicationContext обладает дополнительной функциональностью. Это мапа! ApplicationContext предоставляет: Фабричные методы бина для доступа к компонентам приложения Возможность загружать файловые ресурсы в общем виде Возможность публиковать события и регистрировать обработчики на них Возможность работать с сообщениями с поддержкой неск. языков Наследование от родительского контекста Зачем так много - Чтобы можно было задавать разные способы конфигурирования. FileSystemXmlApplicationContext - указываем полный путь к XML-файлу с конфигурацией бинов (для автономных приложений) ClassPathXmlApplicationContext - XML-файл с конфигурацией бинов помещаем в CLASSPATH (для автономных приложений) XmlWebApplicationContext - загружает XML-файл с метаданными бинов - (веб-приложения) AnnotationConfigApplicationContext - для обычной Java-конфигурации, в качестве аргумента которому передается класс, либо список классов с аннотацией @Configuration, @Component и др. WebApplicationContext - для веб-приложений; ApplicationContext ctx = new FileSystemXmlApplicationContext("c:/bean_properties.xml"); Как можно связать бины? Связывание бинов или внедрение зависимостей происходит по следующему алгоритму: 1. Описание бинов: полностью в .xml файле, в java коде с использованием аннотаций (@Configuration + методы, помеченные аннотацией @Bean, которые возвращают бины) полностью с помощью аннотаций (@Configuration + @ComponentScan + @Component) 2. Внедрение зависимостей (Dependency Injection), может происходить через конструктора (предпочтительно, при этом аннотация не нужна), через сеттеров, через поле над которыми ставиться аннотация @Autowire над чем ставить autowire - хабр статья Что такое Dependency Injection? Dependency Injection (внедрение зависимости) - набор паттернов и принципов разработки программного обеспечения, которые позволяют писать слабосвязанный код. Построением/внедрением зависимостей зависимостей занимается контейнер IoC Spring’a. При помощи DI объекты определяют свои зависимости (то есть другие объекты, с которыми они работают). Всего есть 3 варианта внедрения: через конструктора, через сеттеров, через аннотацию над полем. К достоинствам применения DI можно отнести: Сокращение объема связующего кода. Упрощенная конфигурация приложения. Возможность управления общими зависимостями в единственном репозитории. Улучшенная возможность тестирования. Стимулирование качественных проектных решений для приложений. Реализация DI в Spring основана на двух ключевых концепциях Java — компонентах JavaBean и интерфейсах. За счет применения DI объем кода, который необходим при проектировании приложения на основе интерфейсов, снижается почти до нуля. Кроме того, с помощью интерфейсов можно получить максимальную отдачу от DI, потому что бины могут использовать любую реализацию интерфейса для удовлетворения их зависимости. К типам реализации внедрения зависимостей в Spring относят: @Autowired DI - аннотация Spring, помечают конструктор, поле, сеттер-метод или метод конфигурации, сигнализируя, что им обязательно требуется внедрение зависимостей. Если в контейнере не будет обнаружен необходимый для вставки бин, то будет выброшено исключение, либо можно указать @Autowired (required = false), означающее, что внедрение зависимости в данном месте не обязательно. Constructor DI - зависимости компонента предоставляются ему в его конструкторе. Рекомендуется как основной способ. Setter DI - контейнер IoC внедряет зависимости через методы установки (сеттеры) в стиле JavaBean. Какие бины будут использоваться для настройки приложения? @Configuration - перед классом означает, что класс может быть использован контейнером Spring IoC как конфигурационный класс для бинов. @Bean - перед методом, информирует Spring о том, что возвращаемый данным методом объект должен быть зарегистрирован как бин @ComponentScan("path") - задает путь, по которому спринг будет искать классы для создания бинов. @EnableTransactionManagement - включает функцию управления транзакциями Spring на основе аннотаций (а нужно ли оно?) Как получить данные из файла «.property»? Указываем конфигурацию @PropertySource (classpath:application.properties"). Обращаясь к property.getProperty({ключ}) – вы получаете его значение. Для xml указываем @Value на параметрах конструктора Указываемся@Value("${emp.name}"), при этом должен быть: @Bean public static PropertySourcesPlaceholderConfigurer configurer() { return new PropertySourcesPlaceholderConfigurer(); } Класс Environment и его методы (например private Environment env; env.getProperty()), перед этим необходимо сообщить название файла. В SpringBoot заранее прописан файл application.properties Как запустить Спринг-приложение из-под сервера Tomcat? Добавить конфигурацию Tomcat Расширяем main-класс с помощью SpringBootServletInitializer. В pom.xml указываем war Сделать .jar файлы доступными (перенести в папку webapp/WEB-INF/lib) Добавляем зависимость spring-boot-starter-tomcat // Или добавить tomacat через run - edit configurations. Что такое Artifacts? Артефакты - в широком смысле это некие объекты создаваемые в ходе разработки ПО, например схемы классов, код, документация, инструкции, иконки, картинки и все что сопровождает процесс разработки. В узком смысле – некая выходная сборка вашего проекта со всеми его зависимостями: библиотеками, плагинами, статическими ресурсами предназначенный для тестирования, деплоя. В общем случае их может быть несколько: .jar для десктопа и .war для веба. Для каждого артефакта можно определить правила сборки, развертывания, запуска и т.д. В чем отличие артефакта war от war exploded? war артефакт — упакованный в архив проект, только уже скомпилированный, и в котором изменена структура папок так, чтобы его можно было выкладывать уже напрямую на Tomcat. war exploded - то же самое, только в незаархивированном виде. exploded - распакованная на сервере версия, позволяет обновлять конфигурацию без редеплоя. Какая разница между аннотациями @Component, @Repository и @Service в Spring? @Component - говорит спрингу, что из данного класса нужно сделать бин (как и @Service, @Repository). Аннотация @Component имеет наследников: @Repository, @Service и @Controller. Все они являются частными случаями использования @Component для слоёв DAO, сервиса и контроллера MVC. Технически они одинаковы, но мы используем их для разных целей - добавления отдельной логики приложения @Repository - указывает, что класс выполняет роль хранилища (объект доступа к DAO). @Service - содержат бизнес-логику и вызывает методы на уровне хранилища. @Controller - указывает, что класс выполняет роль контроллера MVC. DispatcherServlet просматривает такие классы для поиска @RequestMapping (используется для мапинга (связывания) с URL для всего класса или для конкретного метода обработчика). Как выглядит структура MVC-приложения? MVC (Model-View-Controller) - шаблон проектирования, который делит логику на три отдельных, но взаимосвязанных компонента таким образом, что модификация каждого компонента может осуществляться независимо. Основная цель MVC — отделить реализацию бизнес-логики приложения (модели) от ее визуализации (вида). Такое разделение повысит возможность повторного использования кода. Модель (Model) - предоставляет данные и реагирует на команды контроллера, изменяя свое состояние. Она содержит всю бизнес-логику приложения. Представление (View) - отвечает за отображение пользователю данных из модели в нужном формате. Spring MVC поддерживает несколько поставщиков View (они называются шаблонизаторы) - Thymeleaf и пр. Контроллер (Controller) - содержит код, который отвечает за обработку действий пользователя (HTTP, GET или POST запросы) и обменивается данными с моделью (любое действие пользователя в системе обрабатывается в контроллере), ссылается на верное представление обработки запроса. Spring Web MVC - веб-фреймворк, основанный на Servlet API, предназначенный для создания веб-приложений на языке Java, с использованием двух самых популярных шаблонов проектирования - Front controller(сервлет) и MVC. Spring Web MVC реализует четкое разделение задач, что позволяет легко разрабатывать и тестировать наши приложения. Данные задачи разбиты между разными компонентами: Dispatcher Servlet, Controllers, View Resolvers, Views, Models, ModelAndView, Model and Session. Front controller (Единая точка входа) - паттерн, где центральный сервлет, DispatcherServlet, принимает все запросы и распределяет их между контроллерами, обрабатывающими разные URL. Ниже приведена последовательность событий, соответствующая входящему HTTP-запросу: После получения HTTP-запроса DispatcherServlet обращается к интерфейсу HandlerMapping, который определяет, какой Контроллер (Controller) должен быть вызван, после чего HandlerAdapter, отправляет запрос в нужный метод Контроллера. Контроллер принимает запрос и вызывает соответствующий служебный метод, основанный на GET, POST и т.д. Вызванный метод формирует данные Модели (например, набор данных из БД) и возвращает их в DispatcherServlet вместе с именем Представления (View) (как правило имя html-файла). При помощи интерфейса ViewResolver DispatcherServlet определяет, какое представление нужно использовать на основании полученного имени и получает в ответе имя представления View. -если это REST-запрос на сырые данные (JSON/XML), то DispatcherServlet сам его отправляет; -если обычный запрос, то DispatcherServlet отправляет данные Модели в виде атрибутов в Представление (View) - шаблонизаторы Thymeleaf, FreeMarker и т.д., которые сами отправляют ответ. Все действия происходят через один единственный DispatcherServlet. Сконфигурировать наше Spring MVC-приложение мы можем с помощью Java-config, добавив зависимость spring-webmvc и установив над классом конфигурации @EnableWebMvc, которая применит дефолтные настройки - зарегистрирует некоторые специальные бины из Spring MVC и адаптирует их к нашим бинам. Но, если требуется тонкая настройка, то мы можем имплементировать интерфейс WebMvcConfigurer и переопределить необходимые методы. Теперь нужно зарегистрировать конфигурацию в Spring Context это позволит сделать созданный нами класс MyWebAppInitializer, который нужно унаследовать от AbstractAnnotationConfigDispatcherServletInitializer, и передать в его методы классы нашей конфигурации RootConfig.class и App1Config.class. Своими внутренними методами он создает два экземпляра WebApplicationContext в виде объектов класса AnnotationConfigWebApplicationContext. Если же у нас только один класс конфигурации, то его нужно передать в метод getRootConfigClasses(), а getServletConfigClasses() должен возвращать null. Чем контроллер отличается от сервлета? Сервлет – это программный модуль Java на стороне сервера, который обрабатывает запросы клиентов и реализует интерфейс сервлета. Могут отвечать на любые запросы, и они обычно используются для расширения приложений, размещаемых на веб-серверах. Front controller (dispatcher servlet) принимает все запросы и перераспределяет их на Controllers, View Resolvers, Views, Models, ModelAndView, Model and Session. Контроллер - описывает логику одного конкретного функционала. Какая основная зависимость фреймворка Спринг? Почему во многих сборках она не указывается явно? Spring core - это транзитивная зависимость, подтягивается сама другими модулями Spring. Это можно увидеть, если нажать на вкладку maven - раздел dependency. Пример - web-mvc Как вернуть страницу в контроллере? Как вернуть данные? В методе контроллера, в возвращаемом значении указать имя представления - model.addAttribute("var_name", data) Model — интерфейс, ModelMap его реализация. ModelAndView является контейнером для пары, как ModelMap и View. @GetMapping("/goToViewPage") public ModelAndView passParametersWithModelAndView() { ModelAndView modelAndView = new ModelAndView("viewPage"); modelAndView.addObject("message", "Baeldung"); return modelAndView; } Уметь рассказать про принципы работы Spring. Spring Framework — один из самых популярных фреймворков для создания приложений на Java. Мы пишем свои классы, прописываем в них часть логики, а создает объекты наших классов и вызывает методы уже сам фреймворк (т.к. в основе лежит IoC and DI). Чаще всего классы имплементируют интерфейсы из фреймворка или наследуют классы из него, таким образом получая часть уже написанной за вас функциональности. Но не обязательно именно так. В спринге стараются по максимуму отойти от жесткой связности (когда ваши классы напрямую зависят от классов/интерфейсов из этого фреймворка), и используют для этой цели аннотации. Основные понятия в спринге это бин и IoC контейнер, который содержит в себе бины. То, какие бины будут находится в контейнере, задается при конфигурации спринга (при помощи xml / java config / аннотаций). После запуска спринг-приложения IoC контейнер, в качестве которого выступает ApplicationContext, содержит в себе набор полностью сконфигурированных бинов со всеми их зависимостями. Далее в коде прописывается где какие бины нужны, при помощи @Autowire над полем / сеттером / конструктором указывается, что данный бин нужно использовать. Структура Spring Framework, состоит из нескольких модулей 1)Inversion of Control - контейнер (Core): делегированное (фреймворку) конфигурирования компонентов приложений и управление жизненным циклом Java-объектов. 2)Фреймворк аспектно-ориентированного программирования (AOP): работает с функциональностью, которая не может быть реализована возможностями ООП на Java без потерь. 3)Фреймворк доступа к данным (Data Access/Integration): работает с системами управления реляционными базами данных на Java-платформе, используя JDBC- и ORM-средства и обеспечивая решения задач, которые повторяются в большом числе Java-based environments. 4)Фреймворк управления транзакциями: координация различных API управления транзакциями и инструментарий настраиваемого управления транзакциями для объектов Java. 5)Фреймворк MVC (Web): каркас, основанный на HTTP и сервлетах, предоставляющий множество возможностей для расширения и настройки. 6)Фреймворк удаленного доступа: конфигурируемая передача Java-объектов через сеть в стиле RPC, поддерживающая RMI, CORBA, HTTP-based протоколы, включая web-сервисы (SOAP). 7)Фреймворк Spring Security: конфигурируемые процессы аутентификации и авторизации. 8) Фреймворк удалённого управления: конфигурируемое представление и управление Java-объектами для локальной или удалённой конфигурации с помощью JMX. 9) Фреймворк работы с сообщениями (Messaging): конфигурируемая регистрация объектов-слушателей сообщений для прозрачной обработки сообщений из очереди сообщений с помощью JMS, улучшенная отправка сообщений по стандарту JMS API. 10)Тестирование (test): каркас, поддерживающий классы для написания модульных и интеграционных тестов. Конфигурация Spring - приложения (в порядке приоритетности): автоматическая конфигурация; если при помощи автоматической конфигурации нет возможности правильно настроить все возможные бины — использовать джава-конфигурацию (создание объектов используя джава код); ну и самый низкоприоритетный способ — это по-старинке, используя xml конфиги. Связывание бинов и их жизненный цикл. Связывание: Связыванием бинов в спринг называется внедрение в бины зависимостей при их инициализации. Это можно делать явно, указывая в конфигурационном xml файле зависимости с помощью тегов , а также: 1)Связывание над сеттерами аннотацией @Autowired. 2)Через поле и аннотацию, которая подтянет бин в классе AppConfig. Данный метод обозначен аннотацией @Bean, что автоматически подтягивает аргументы в метод. 3)Также возможно конструировать через связывание по @Autowired с помощью конструктора. Необходимо пометить все классы, которые являются бинами аннотацией @Component.Чтобы Спринг видел все бины, в классе AppConfig добавить аннотацию @ComponentScan. Жизненный цикл бина: Запуск Spring приложение - запускается Spring контейнер, далее проходится по всем файлам и если видит аннотацию Bean - создается объект бина, затем внедряются зависимости (Dependency Injection) - затем вызывается init метод у данного бина - бин будет готов к использованию и пользователь получит доступ к нему - когда пользователь завершит приложение - спринг вызовет дестрой метод - и затем приложение остановится. Подробно: создание объекта бина, через конструктор new() внедрение зависимостей нотификация aware-интерфейсов (реализация данных интерфейсов может добавлять бинам какой-то специфичный функционал) пред-инициализация в методах .PostProcessBeforeInitialization() интерфейса BeanPostprocessor инициализация (может быть разными способами) - @PostConstract - .afterPropertiesSet() бина под интерфейсом InitializingBean - Init-метод (либо прописать в xml, либо @Bean(initMethod = "init")) пост-инициализация (донастройка бина) в методах .PostProcessAfterInitialization() интерфейса BeanPostprocessor использование бина уничтожение бина при завершении работы IoC контейнера (также может быть разными способами): - Метод бина с аннотацией @PreDestroy - Метод указанный в свойстве destroyMethod определения бина - Метод destroy() интерфейса DisposableBean Основные паттерны Spring. Proxy (Заместитель) - представляет функциональные возможности другого класса. Объект-оболочка или агент, который вызывается клиентом для доступа к реальному обслуживающему объекту за кулисами. Обеспечивает защиту исходного объекта от внешнего мира. Singleton (Одиночка) - гарантирует, что в памяти будет существовать только один экземпляр объекта, который будет предоставлять сервисы. Factory (Фабрика) - позволяет инициализировать объект через фабричный метод (BeanFactory - Простой контейнер, который обеспечивает базовую поддержку Dependency Injection. Для работы с этим контейнером используется интерфейс org.springframework.beans.factory.BeanFactory) Этот паттерн позволяет инициализировать объект через публичный статический метод, называемый фабричным методом. Spring использует паттерн Factory для создания объекта бина с использованием следующих двух подходов: BeanFactory и ApplicationContext. ApplicationContext - является центральным интерфейсом в приложении Spring для предоставления информации о конфигурации приложения. Объявляет функции, которые читают параметры property-файлов и обрабатывают события. Для работы с этим контейнером используется интерфейс org.springframework.context.ApplicationContext. Template (Шаблон) - паттерн широко используется для работы с повторяющимся бойлерплейт (шаблонным) кодом (таким как, закрытие соединений и т. п.). Model View Controller (Модель-Представление-Контроллер) - основная задача - отделить логику от визуализации. Паттерн основан на Servlet API. В данном паттерне компоненты не зависят друг от друга и каждый отвечает за определенную задачу. Front Controller (Контроллер запросов) - Spring предоставляет DispatcherServlet, чтобы гарантировать, что входящий запрос будет отправлен вашим контроллерам. Паттерн используется для того, чтобы все запросы обрабатывались одним обработчиком и передавались в main, что так же в свою очередь обеспечивает дополнительную безопасность и удобство для разработчика. View Helper (Вспомогательный компонент представления) - отделяет статическое содержимое в представлении, такое как JSP, HTML, от обработки бизнес-логики. У спринга есть своя библиотека для инкапсуляции логики обработки в хелперах. Service Locator (Локатор служб) - ServiceLocatorFactoryBean сохраняет информацию обо всех бинах в контексте. Когда клиентский код запрашивает сервис (бин) по имени, он просто находит этот компонент в контексте и возвращает его. Клиентскому коду не нужно писать код, связанный со Spring, чтобы найти бин. Service Locator - паттерн используется, когда мы хотим найти различные сервисы, используя JNDI. Учитывая высокую стоимость поиска сервисов в JNDI, Service Locator использует кеширование. При запросе сервиса первый раз Service Locator ищет его в JNDI и кэширует объект. Дальнейший поиск этого же сервиса через Service Locator выполняется в кэше, что значительно улучшает производительность приложения. Observer-Observable (Наблюдатель) - Используется в механизме событий ApplicationContext. Определяет зависимость "один-ко-многим" между объектами, чтобы при изменении состояния одного объекта все его подписчики уведомлялись и обновлялись автоматически. Context Object (Контекстный объект) - паттерн инкапсулирует системные данные в объекте-контексте для совместного использования другими частями приложения без привязки приложения к конкретному протоколу. Chain of Responsibility - это поведенческий паттерн проектирования, позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи. Подробнее: https://docs.google.com/document/d/1UtG9wR9qoJVxiPeR2an9QoFjfbizZE3QHQ1QWufusBQ/edit |