每天进步一点点,好记性不如烂笔头

导航

观察者模式

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

观察者模式(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

 

posted on 2017-06-16 23:06  yujiwei  阅读(185)  评论(0编辑  收藏  举报