zoukankan      html  css  js  c++  java
  • 观察者模式

    观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。

    观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

    观察者模式一般有以下几种角色: 
    ● Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法snedNotify()。目标类可以是接口,也可以是抽象类或具体类。 
    ● ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。 
    ● Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。 
    ● ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。

     具体代码演示:

    工程结构如下:

    创建发布消息的实体类:

     1 package com.sunyard.bean;
     2 
     3 /**
     4  * <p>发布招聘信息类</p>
     5  * @author:774346810@qq.com
     6  * @date:2017-6-25
     7  */
     8 public class Job {
     9     private String title;//招聘标题
    10     
    11     public Job(String title) {
    12         this.title = title;
    13     }
    14 
    15     public String getTitle() {
    16         return title;
    17     }
    18 
    19     public void setTitle(String title) {
    20         this.title = title;
    21     }
    22 }    

    创建抽象观察者:

     1 package com.sunyard.observer;
     2 
     3 import com.sunyard.subject.Subject;
     4 
     5 /**
     6  * <p>抽象观察者类</p>
     7  * @author:774346810@qq.com
     8  * @date:2017-6-25
     9  */
    10 public interface Observer {
    11     //声明响应方法,当某个状态触发时,调用该方法进行相应的操作
    12     public void update(Subject subject);
    13 }

    具体观察者:

     1 package com.sunyard.observer;
     2 
     3 import com.sunyard.subject.HR;
     4 import com.sunyard.subject.HeadHunter;
     5 import com.sunyard.subject.Subject;
     6 
     7 /**
     8  * <p>具体观察者</p>
     9  * @author:774346810@qq.com
    10  * @date:2017-6-25
    11  */
    12 public class JobSeeker implements Observer{
    13     private String name;
    14     
    15     public JobSeeker(String name){
    16         this.name = name;
    17     }
    18     
    19     @Override
    20     public void update(Subject subject) {
    21         if(subject instanceof HeadHunter){
    22             System.out.println("求职者的名字是:" + name);
    23             System.out.println("HeadHunter更新了职位信息");
    24             System.out.println(((HeadHunter) subject).getName());
    25             System.out.println("职位信息如下:");
    26             System.out.println(((HeadHunter) subject).getLastJob().getTitle());
    27         } else if(subject instanceof HR){
    28             System.out.println("求职者的名字是:" + name);
    29             System.out.println("HeadHunter更新了职位信息");
    30             System.out.println(((HR) subject).getName());
    31             System.out.println("职位信息如下:");
    32             System.out.println(((HR) subject).getLastJob().getTitle());
    33         }
    34     }
    35     
    36 }
     1 package com.sunyard.observer;
     2 
     3 import com.sunyard.subject.HR;
     4 import com.sunyard.subject.HeadHunter;
     5 import com.sunyard.subject.Subject;
     6 
     7 /**
     8  * <p>具体观察者</p>
     9  * @author:774346810@qq.com
    10  * @date:2017-6-25
    11  */
    12 public class DBManager implements Observer{
    13     private String name;
    14 
    15     public DBManager(String name) {
    16         this.name = name;
    17     }
    18     
    19     @Override
    20     public void update(Subject subject) {
    21         if(subject instanceof HeadHunter){
    22             System.out.println("求职者的名字是:" + name);
    23             System.out.println("HeadHunter更新了职位信息");
    24             System.out.println(((HeadHunter) subject).getName());
    25             System.out.println("职位信息如下:");
    26             System.out.println(((HeadHunter) subject).getLastJob().getTitle());
    27         } else if(subject instanceof HR){
    28             System.out.println("求职者的名字是:" + name);
    29             System.out.println("HeadHunter更新了职位信息");
    30             System.out.println(((HR) subject).getName());
    31             System.out.println("职位信息如下:");
    32             System.out.println(((HR) subject).getLastJob().getTitle());
    33         }
    34     }
    35 }

    创建抽奖被观察者:

     1 package com.sunyard.subject;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import com.sunyard.observer.Observer;
     7 
     8 /**
     9  * <p>抽象被观察者</p>
    10  * @author:774346810@qq.com
    11  * @date:2017-6-25
    12  */
    13 public abstract class Subject {
    14     //定义一个观察者集合用于存储所有的观察者对象
    15     protected List<Observer> observers = new ArrayList<Observer>();
    16     
    17     //注册方法,用于向观察者集合中增加一个观察者
    18     public void attach(Observer observer){
    19         observers.add(observer);
    20     }
    21     
    22     //注销方法,用于在观察者集合中删除一个观察者
    23     public void detach(Observer observer) {
    24         observers.remove(observer);
    25     }
    26     
    27     //声明抽象通知方法
    28     public abstract void sendNotify(Subject subject);
    29 }

    创建具体被观察者:

     1 package com.sunyard.subject;
     2 
     3 import com.sunyard.bean.Job;
     4 import com.sunyard.observer.Observer;
     5 /**
     6  * <p>具体被观察者</p>
     7  * @author:774346810@qq.com
     8  * @date:2017-6-25
     9  */
    10 public class HeadHunter extends Subject{
    11     private String name;
    12     
    13     private Job myJobLast;//最新发布的招聘信息
    14     
    15     public HeadHunter(String name){
    16         this.name = name;
    17     }
    18     
    19     // 发布招聘,发布时发送通知
    20     public void publishJob(Job job) {
    21         myJobLast = job;
    22         sendNotify(this);
    23     }
    24 
    25     public String getName() {
    26         return name;
    27     }
    28 
    29     public Job getLastJob() {
    30         return myJobLast;
    31     }
    32     
    33     @Override
    34     public void sendNotify(Subject subject) {
    35         //遍历观察者集合,调用每一个观察者的响应方法
    36         for(Observer observer : observers){
    37             observer.update(subject);
    38         }
    39     }
    40     
    41 }
     1 package com.sunyard.subject;
     2 
     3 import com.sunyard.bean.Job;
     4 import com.sunyard.observer.Observer;
     5 
     6 /**
     7  * <p>具体被观察者</p>
     8  * @author:774346810@qq.com
     9  * @date:2017-6-25
    10  */
    11 public class HR extends Subject{
    12     private String name;
    13     
    14     private Job myJobLast;//最新发布的招聘
    15     
    16     public HR(String name){
    17         this.name = name;
    18     }
    19     
    20     // 发布招聘,发布时发送通知
    21     public void publishJob(Job job) {
    22         myJobLast = job;
    23         sendNotify(this);
    24     }
    25 
    26     public Job getLastJob() {
    27         return myJobLast;
    28     }
    29     
    30     public String getName() {
    31         return name;
    32     }
    33 
    34     @Override
    35     public void sendNotify(Subject subject) {
    36         //遍历观察者集合,调用每一个观察者的响应方法
    37         for (Observer observer : observers) {
    38             observer.update(subject);
    39         }
    40     }
    41     
    42 }

    观察者测试类:

     1 package com.sunyard.test;
     2 
     3 import com.sunyard.bean.Job;
     4 import com.sunyard.observer.DBManager;
     5 import com.sunyard.observer.JobSeeker;
     6 import com.sunyard.subject.HR;
     7 import com.sunyard.subject.HeadHunter;
     8 
     9 /**
    10  * <p>测试观察者</p>
    11  * @author:774346810@qq.com
    12  * @date:2017-6-25
    13  */
    14 public class ObserverPattern {
    15     public static void main(String[] args) {
    16         HeadHunter headHunter = new HeadHunter("猎头");
    17         
    18         HR hr = new HR("人事");
    19         
    20         JobSeeker jobSeeker1 = new JobSeeker("求职者1");
    21         JobSeeker jobSeeker2 = new JobSeeker("求职者2");
    22         JobSeeker jobSeeker3 = new JobSeeker("求职者3");
    23         
    24         DBManager dbManager = new DBManager("管理员");
    25         
    26         //完成订阅注册添加
    27         headHunter.attach(jobSeeker1);
    28         headHunter.attach(jobSeeker2);
    29         headHunter.attach(jobSeeker3);
    30         headHunter.attach(dbManager);
    31         
    32         //猎头发布招聘,将会依次给观察者发通知
    33         headHunter.publishJob(new Job("工作信息1"));
    34         
    35         //移除某个观察者
    36         headHunter.detach(jobSeeker2);
    37         
    38         //再次发布招聘,测试移除订阅
    39         headHunter.publishJob(new Job("工作信息2"));
    40         
    41         hr.attach(jobSeeker2);
    42         hr.attach(dbManager);
    43         
    44         hr.publishJob(new Job("工作信息3"));
    45     }
    46 }

    输入结果:

     1 求职者的名字是:求职者1
     2 HeadHunter更新了职位信息
     3 猎头
     4 职位信息如下:
     5 工作信息1
     6 求职者的名字是:求职者2
     7 HeadHunter更新了职位信息
     8 猎头
     9 职位信息如下:
    10 工作信息1
    11 求职者的名字是:求职者3
    12 HeadHunter更新了职位信息
    13 猎头
    14 职位信息如下:
    15 工作信息1
    16 求职者的名字是:管理员
    17 HeadHunter更新了职位信息
    18 猎头
    19 职位信息如下:
    20 工作信息1
    21 求职者的名字是:求职者1
    22 HeadHunter更新了职位信息
    23 猎头
    24 职位信息如下:
    25 工作信息2
    26 求职者的名字是:求职者3
    27 HeadHunter更新了职位信息
    28 猎头
    29 职位信息如下:
    30 工作信息2
    31 求职者的名字是:管理员
    32 HeadHunter更新了职位信息
    33 猎头
    34 职位信息如下:
    35 工作信息2
    36 求职者的名字是:求职者2
    37 HeadHunter更新了职位信息
    38 人事
    39 职位信息如下:
    40 工作信息3
    41 求职者的名字是:管理员
    42 HeadHunter更新了职位信息
    43 人事
    44 职位信息如下:
    45 工作信息3
  • 相关阅读:
    偶串_牛客网
    制造回文_牛客网
    字典树(前缀树)的实现
    动态规划LeetCode174地下城游戏
    动态规划LeetCode64最小路径和
    动态规划LeetCode300最长上升子序列
    动态规划LeetCode120三角形最小路径和
    Zabbix 监控sqlserver
    如何回收VCSA 6自带的vPostgres数据库空间
    领益科技:导出Wireless组中的成员
  • 原文地址:https://www.cnblogs.com/yujiwei/p/7029545.html
Copyright © 2011-2022 走看看