Вы до сих пор помните, как гангстеры сотрудничали в фильме полиции и гангстера? Когда банда - кража со взломом, один или два человека всегда берут ветер у двери. Если есть какое -либо движение, сообщники внутри будут немедленно уведомлены о срочном отступлении. Возможно, человек, который позволяет новостям, не обязательно знает каждого сообщника в этом; И может быть новый младший брат, который не знает того, кто дает новости. Но это ничто, это не может повлиять на их связь, потому что у них есть код, который был согласован.
Ха -ха, связь между воздушным вентером и упомянутым выше вором является живым примером модели наблюдателя в реальности.
Режим наблюдателя также известен как режим публикации/подписки. GOF определяет шаблон наблюдателя следующим образом: определяет зависимость от одного ко многим между объектами. Когда состояние объекта меняется, все объекты, которые зависят от него, уведомляются и автоматически обновляются.
Здесь я впервые расскажу о важном принципе объектно -ориентированного дизайна - принципа единой ответственности. Следовательно, каждый объект системы должен сосредоточиться на дискретных абстракциях в проблемной области. Следовательно, в идеале объект делает только одно. Это приносит много преимуществ в разработке: он обеспечивает повторное использование и обслуживание, а также является хорошей основой для рефакторинга.
Поэтому почти все шаблоны дизайна основаны на этом основном принципе дизайна. Я думаю, что происхождение модели наблюдателя должно быть при обработке графического интерфейса и бизнес -данных, потому что большинство примеров, объясняющих модель наблюдателя, теперь являются этой темой. Однако применение режима наблюдателя ни в коем случае не ограничено этим аспектом.
Что ж, понимание определения всегда требует случаев для анализа. Учетные записи WeChat в настоящее время довольно популярны. Давайте представим вам модель наблюдателя с фоном учетных записей услуг WeChat.
Посмотрите на картинку:
Каждый пользователь имеет 3 строки на рисунке выше, которые опущены, чтобы прояснить изображение.
Как показано на рисунке выше, номер службы - наша тема, а пользователь - наблюдатель. Теперь мы уточняем следующие функции:
1. Сервисная учетная запись - это тема, а бизнес разжигает сообщения
2. Наблюдатели должны только подписаться на тему, и они будут отправлены, как только появятся новые новости.
3. Отписаться, когда вы не хотите этого тематического сообщения
4. Пока учетная запись услуг все еще там, кто -то будет подписан. Теперь давайте посмотрим на классную диаграмму схемы наблюдателя:
Далее идет время кода, мы моделируем учетную запись услуги WeChat 3D лотереи и некоторых подписчиков.
Во -первых, начните писать о нашем интерфейсе темы и интерфейсе наблюдателя:
пакет com.zhy.pattern.observer; / ** * Интерфейс темы, все темы должны реализовать этот интерфейс * * @author zhy * */ public interface subject {/ ** * Зарегистрировать наблюдатель * * @param stemver */ public void Registerobserver (наблюдение за наблюдателем); / ** * Удалить наблюдатель * * @param stemver */ public void removeObserver (Observer Observer); / *** Уведомление всех наблюдателей*/ public void notifyobservers (); } пакет com.zhy.pattern.observer; / *** @author Zhy Все наблюдатели должны реализовать этот интерфейс*/ public interface stemver {public void update (String msg); }Следующее 3D -номера обслуживания. Класс реализации:
пакет com.zhy.pattern.observer; импортировать java.util.arraylist; импортировать java.util.list; Общедоступный класс ObjectFor3d реализует субъект {Private List <Beaserver> Наблюдатели = new ArrayList <Searver> (); / *** 3D Номер лотереи*/ Private String MSG; @Override public void Registerobserver (Observer stemver) {stemvers.Add (Observer); } @Override public void removeObserver (stemver stemver) {int index = ebservers.indexof (stemver); if (index> = 0) {stemvers.remove (index); }} @Override public void notifyObservers () {for (stemver stemver: stairvers) {exerver.update (msg); }} / ** * Сообщение об обновлении темы * * @param msg * / public void setmsg (String msg) {this.msg = msg; notifyObservers (); }}Моделируйте двух пользователей:
пакет com.zhy.pattern.observer; Общедоступный Class Observer1 реализует наблюдатель {частный предмет; public stemver1 (субъект субъекта) {this.subject = субъект; субъект. RegisterObserver (это); } @Override public void update (String msg) {System.out.println ("stemver1 получает 3D номер ->" + msg + ", я хочу записать его."); }} пакет com.zhy.pattern.observer; Общедоступный Class Observer2 реализует наблюдатель {частный предмет; public stemver2 (субъект) {this.subject = субъект; субъект. RegisterObserver (это); } @Override public void update (String msg) {System.out.println ("stemver2 получает 3D номер ->" + msg + "Я хочу рассказать своим соседам по комнате."); }} Можно видеть, что все пользователи, которые подписываются на сообщения, поддерживаются в учетной записи службы, и все пользователи уведомляются, когда есть новое сообщение в учетной записи службы. Вся архитектура является свободной связью, и реализация темы не зависит от пользователя. Когда новый пользователь добавляется, код темы не нужно изменять; Как пользователь обрабатывает полученные данные, не имеет ничего общего с темой;
Наконец, посмотрите на тестовый код:
пакет com.zhy.pattern.observer.test; Импорт com.zhy.pattern.observer.objectfor3d; Импорт com.zhy.pattern.observer.observer; Импорт com.zhy.pattern.observer.observer1; Импорт com.zhy.pattern.observer.observer2; Импорт com.zhy.pattern.observer.subject; открытый тест класса {public static void main (string [] args) {// моделировать 3D -номер службы objectFor3d субъект forFor3d = new ObjectFor3d (); // customer1 stember stemver1 = new Observer1 (SubjectFor3d); Stemver xersver2 = new xersver2 (subjectfor3d); SubjectFor3D.SetMsg ("3D -номер 20140420: 127"); SubjectFor3D.SetMsg ("3D -номер 20140421: 333"); }}Результат вывода:
Наблюдатель1 Получает 3D -номер -> 3D -номер 20140420: 127, я хочу записать его. Наблюдает 2 -й номер 3D -> 3D -номер 20140420: 127 Я хочу рассказать своим соседям по комнате. Наблюдатель1 получает 3D -номер -> 3D -номер 20140421: 333, я хочу записать его. Наблюдает 2 -й номер 3D -> 3D -номер 20140421: 333 Я хочу рассказать своим соседям по комнате.
В JDK или Andorid есть много мест, которые реализуют режим наблюдателя, такие как xxxview.addxxxlistenter. Конечно, xxxview.setonxxxlistener не обязательно является режимом наблюдателя, потому что режим наблюдателя представляет собой отношения с одним ко многим. Для setxxxlistener это отношения 1-к-1, и его следует назвать обратным вызовом.
Поздравляем с изучением режима наблюдателя. Приведенный выше режим наблюдателя позволяет нам выписывать его с нуля. Конечно, Java помогла нам внедрить режим наблюдателя с помощью java.util.observable и java.util.observer.
Ниже мы используем встроенные классы Java для реализации шаблона наблюдателя:
Прежде всего, есть тема 3D лотерейной службы:
пакет com.zhy.pattern.observer.java; импортировать java.util.observable; Общедоступный класс субъект Forfor3d Extends issableble {Private String MSG; public String getMsg () {return msg; } / ** * Сообщение об обновлении темы * * @param msg * / public void setmsg (String msg) {this.msg = msg; setChanged (); notifyObservers (); }}Ниже приведена тема номера обслуживания с двойным цветом:
пакет com.zhy.pattern.observer.java; импортировать java.util.observable; Public Class SubjectForsSQ Extends Observable {Private String MSG; public String getMsg () {return msg; } / ** * Сообщение об обновлении темы * * @param msg * / public void setmsg (String msg) {this.msg = msg; setChanged (); notifyObservers (); }}Наконец, наши пользователи:
пакет com.zhy.pattern.observer.java; импортировать java.util.observable; импортировать java.util.observer; Public Class Observer1 реализует наблюдатель {public void registersUbject (наблюдаемый наблюдаемый) {vaseleble.addobserver (this); } @Override public void update (наблюдаемая o, объект arg) {if (o exactionof tootfor3d) {subjectfor3d субъект forfor3d = (subjectfor3d) o; System.out.println ("SubjectFor3D MSG ->" + subjectFor3d.getMsg ()); } if (o encosefureforssq) {subjectForsSq SubjectForsSQ = (subjectForsSQ) O; System.out.println ("SubjectForsSQ's MSG ->" + subjectForsSq.getMsg ()); }}}Посмотрите на тестовый код:
пакет com.zhy.pattern.observer.java; открытый тест класса {public static void main (string [] args) {subjectfor3d субъект 3d = new SubjectFor3d (); SubjectForsSQ SubjectForsSQ = New SubjectForsSQ (); Stemver1 stemver1 = new Observer1 (); stemver1.registersUbject (субъект 3D); stemver1.registersUbject (subjectForsSQ); SubjectFor3D.SetMsg ("Привет 3d'nums: 110"); SubjectForsSQ.SetMsg ("ssq'nums: 12,13,31,5,4,3 15"); }}Результаты теста:
Subjectfor3d's MSG -> Hello 3d'nums: 110 SubjectForsSQ's MSG -> SSQ'NUMS: 12,13,31,5,4,3 15
Можно видеть, что использование встроенных классов Java для реализации шаблона наблюдателя, код очень краткий. Кстати, AddoBserver, RemoveObserver, для нас были реализованы. Все, что мы можем видеть, что наблюдаемое - это класс, а не интерфейс. По сути, книга негативно относится к дизайну Java. Такое ощущение, что встроенная модель наблюдателя Java нарушает принцип программирования, ориентированного на интерфейс. Однако, если вы думаете об этом, вы действительно пишете образец наблюдателя здесь (наша собственная реализация). Идея интерфейса очень хороша, но если вы продолжите добавлять много тем, DDobserver, RemeableObserver, уведомление о каждой теме в основном одинаковы. Интерфейсы не могут реализовать повторное использование кода, и невозможно использовать комбинированный режим для достижения повторного использования этих трех методов, поэтому я думаю, что разумно реализовать эти три метода в классе здесь.