Статья включена в GitHubJavaKeeper, в том числе необходимые навыки и оружие для разработки N-line интернета
В программных системах часто встречается такое требование: если состояние объекта изменяется, некоторые объекты, связанные с ним, также вносят соответствующие изменения.
- Публичная учетная запись WeChat, если пользователь подписывается на публичную учетную запись, то он будет получать сообщения от публичной учетной записи, тогда публичная учетная запись является «наблюдаемой», а пользователь — «наблюдателем».
- Метеостанция может публиковать ежедневные прогнозы температуры, влажности, атмосферного давления и т. д. на различные сторонние веб-сайты в виде объявлений.Если данные о погоде обновляются, она должна иметь возможность уведомлять третью сторону в режиме реального времени. метеостанция здесь - "наблюдатель"., сторонний сайт - "Наблюдатель"
- Связь между моделью и представлением в шаблоне MVC также относится к наблюдению и наблюдаемому.
Шаблон Observer — один из наиболее часто используемых шаблонов проектирования.
Шаблон наблюдателя включает два типа объектов: цель наблюдения и наблюдатель.Цель может иметь любое количество наблюдателей, которые зависят от нее.Как только состояние цели наблюдения изменится, все наблюдатели будут уведомлены.
определение
Шаблон наблюдателя: определите зависимость между объектами «один ко многим», чтобы при изменении состояния каждого объекта все объекты, зависящие от него, получали уведомление и автоматически обновлялись.
Паттерн наблюдатель — этоШаблоны поведения объектов.
Псевдонимы для шаблона наблюдателя включают шаблон публикации/подписки, шаблон модели/представления, шаблон источника/слушателя или шаблон зависимых элементов.
Если присмотреться, публикация и подписка несколько отличаются от наблюдателей, то можно понять, что режим публикации-подписки относится к режиму наблюдателя в широком смысле.
Роль
-
Предмет: Наблюдаемый, который относится к наблюдаемому объекту. Как видно из диаграммы классов, в классе есть контейнер Vector для хранения объекта-наблюдателя (причина использования Vector вместо List в том, что Vector безопасен, а List небезопасен при многопоточной работе. ), этот векторный контейнер является ядром наблюдаемого класса, и есть еще три метода: метод присоединения — добавление объекта-наблюдателя в контейнер; метод отсоединения — удаление объекта-наблюдателя из контейнера; метод уведомления — вызов наблюдатель в последовательности Соответствующий метод объекта. Эта роль может быть интерфейсом, абстрактным классом или конкретным классом.Поскольку во многих случаях он смешивается с другими шаблонами, часто используются абстрактные классы.
-
БетонТема: Конкретная цель является подклассом целевого класса, обычно она содержит часто изменяемые данные, и когда ее состояние изменяется, она уведомляет своих различных наблюдателей. Он также реализует абстрактные методы бизнес-логики, определенные в целевом классе (если таковые имеются). Если целевой класс не нуждается в расширении, конкретный целевой класс можно не указывать.
-
Наблюдатель: наблюдатель будет реагировать на изменения в цели наблюдения, и наблюдатель обычно определяется какинтерфейс, который объявляет методы для обновления данных
update()
, поэтому его еще называютабстрактный наблюдатель. -
ConcreteObserver (конкретный наблюдатель): поддерживает ссылку на конкретный целевой объект в конкретном наблюдателе, который хранит соответствующее состояние конкретного наблюдателя, которое должно быть согласовано с состоянием конкретной цели; он реализует метод update(), определенный в абстрактном наблюдателе Observer . Обычно в реализации вы можете вызвать метод attach() определенного целевого класса, чтобы добавить себя в коллекцию целевого класса или удалить себя из коллекции целевого класса с помощью метода detach().
Диаграмма классов
Затем запишите меры предосторожности диаграммы классов UML, здесь моя темаабстрактный метод, так что используйте ***курсив***, абстрактные методы также должны использовать курсив, и конкретные значения различных стрелок, которые я также резюмировал перед «Приквелом шаблона проектирования - что вам нужно знать перед изучением шаблонов проектирования» (различные онлайн Пост отравил себя, записывайте внимательно~~~).
пример
1. Определите интерфейс наблюдателя
interface Observer {
public void update();
}
2. Определите наблюдаемое
abstract class Subject {
private Vector<Observer> obs = new Vector();
public void addObserver(Observer obs){
this.obs.add(obs);
}
public void delObserver(Observer obs){
this.obs.remove(obs);
}
protected void notifyObserver(){
for(Observer o: obs){
o.update();
}
}
public abstract void doSomething();
}
3. Конкретный наблюдатель
class ConcreteSubject extends Subject {
public void doSomething(){
System.out.println("被观察者事件发生改变");
this.notifyObserver();
}
}
4. Конкретный наблюдатель
class ConcreteObserver1 implements Observer {
public void update() {
System.out.println("观察者1收到信息,并进行处理");
}
}
class ConcreteObserver2 implements Observer {
public void update() {
System.out.println("观察者2收到信息,并进行处理");
}
}
5. Клиент
public class Client {
public static void main(String[] args){
Subject sub = new ConcreteSubject();
sub.addObserver(new ConcreteObserver1()); //添加观察者1
sub.addObserver(new ConcreteObserver2()); //添加观察者2
sub.doSomething();
}
}
вывод
被观察者事件发生改变
观察者1收到信息,并进行处理
观察者2收到信息,并进行处理
Как видно из текущих результатов, мы вызываем толькоSubject
метод, но связанные методы обоих наблюдателей вызываются одновременно. Присмотритесь к коду, он на самом деле очень простой, просто вSubject
Ассоциироваться в классеObserver
класс, и вdoSomething()
повторите методObserver
изupdate()
метод подойдет.
Преимущества и недостатки
преимущество
- Уменьшите отношение связи между целью и наблюдателем, это абстрактные отношения связи.
- Между целью и наблюдателем устанавливается спусковой механизм
- Поддержка широковещательной связи
- Соответствовать требованиям «принципа открыт-закрыт».
недостаток
- Зависимость между целью и наблюдателем устранена не полностью, и есть возможность циклических ссылок
- При большом количестве объектов-наблюдателей выпуск уведомлений занимает много времени, что сказывается на эффективности работы программы.
применение
Шаблон наблюдателя в JDK
Шаблон наблюдателя занимает очень важное место в языке Java. В пакете java.util JDK предоставляется класс Observable и интерфейс Observer, которые представляют собой поддержку JDK режима наблюдателя (вы можете проверить исходный код, написание более строгое). но устарело в Java9.
Образец наблюдателя весной
Модель Spring, управляемая событиями, также является классическим применением шаблона наблюдателя. Это самый распространенный обработчик событий в наших общих проектах.
1. Четыре роли шаблона Observer в Spring
-
Событие: ApplicationEventЯвляется родительским классом всех объектов событий. ApplicationEvent наследуется от EventObject jdk, все события должны наследовать ApplicationEvent и получать источник события через источник.
Spring также предоставляет нам множество встроенных событий,
ContextRefreshedEvent
,ContextStartedEvent
,ContextStoppedEvent
,ContextClosedEvent
,RequestHandledEvent
. -
Прослушиватель событий: ApplicationListener, то есть наблюдатель, наследуется от EventListener jdk, и в этом классе есть только один метод onApplicationEvent. Этот метод будет выполнен, когда произойдет отслеживаемое событие.
-
Источник события: ApplicationContext,
ApplicationContext
Это основной контейнер в Spring.При мониторинге событий ApplicationContext можно использовать в качестве издателя событий, то есть источника событий. Поскольку ApplicationContext наследуется от ApplicationEventPublisher. существуетApplicationEventPublisher
Метод публикации событий определяется в:publishEvent(Object event)
-
Управление событиями: ApplicationEventMulticaster, используемый для регистрации прослушивателя событий и трансляции событий. Через него осуществляется регистрация прослушивателя, и его роль заключается в передаче события, опубликованного Applicationcontext, в его список прослушивателей.
2. coding~~~~~~
1. Определите событие
public class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
System.out.println("my Event");
}
}
2. Реализуйте прослушиватели событий
@Component
class MyListenerA implements ApplicationListener<MyEvent> {
public void onApplicationEvent(MyEvent AyEvent) {
System.out.println("ListenerA received");
}
}
@Component
class MyListenerB implements ApplicationListener<MyEvent> {
public void onApplicationEvent(MyEvent AyEvent) {
System.out.println("ListenerB received");
}
}
3. Издатель мероприятия
@Component
public class MyPublisher implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
public void publishEvent(ApplicationEvent event){
System.out.println("publish event");
applicationContext.publishEvent(event);
}
}
4. Протестируйте, сначала внедрите MyPublisher в Spring с аннотациями.
@Configuration
@ComponentScan
public class AppConfig {
@Bean(name = "myPublisher")
public MyPublisher myPublisher(){
return new MyPublisher();
}
}
public class Client {
@Test
public void main() {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyPublisher myPublisher = (MyPublisher) context.getBean("myPublisher");
myPublisher.publishEvent(new MyEvent(this));
}
}
5. Выход
my Event
publish event
ListenerA received
ListenerB received
болтать
Шаблон проектирования на самом деле просто идея дизайна. Вам не нужно иметь несколько наблюдателей, чтобы использовать шаблон наблюдателя. У меня есть только один наблюдатель. Я также использую его.
Чтобы дать еще один каштан, я реклама (файл продукта для рекламы, как правило, xml), если есть какой-то простаивающий трафик в моем рекламном пространстве, я должен использовать его, поэтому я буду использовать Taobao или Pinxixi. открытый API на Duoduoke. В настоящее время я также могу использовать режим наблюдателя. Каждый раз, когда я запрашиваю 100 000 продуктов, я буду создавать новый файл продукта. В это время я также могу использовать режим наблюдателя для получения продуктов. Класс является наблюдаемым объектом, а наблюдатель, который записывает файл товаров, является наблюдателем Когда количество товаров достигает 100 000, наблюдатель уведомляется о необходимости перезаписи в новый файл.
Начальник может подумать, что это сложно реализовать таким образом, независимо от того, нужен ли вам шаблон проектирования, или вы можете использовать очередь сообщений, на самом деле это просто средство, выберите то, что подходит для вашего бизнеса. , и будь счастлив.