设计模式之观察者模式

观察者模式我消化了两天,因为智商问题,理解的比较慢。。。另外恭喜我自己以科目二一百分的成绩顺利拿上驾照

言归正传,先从大神那里扒一张图,对着图看比较容易理解。

        

 

                      (图片来自左潇龙大佬,本图片仅供仅供学习使用,希望大佬不要怪罪)

  观察者模式又称为发布订阅模式,这个模式由被观察者、观察者组成,他们的关系是观察者观察被观察者,当被观察者的状态发生改变的时候会通知对应的观察者。

  简单点概括成通俗的话来说,就是一个类管理着所有依赖于它的观察者类,并且它状态变化时会主动给这些依赖它的类发出通知。

  JDK中提供了观察者模式现成的代码,贴出来说明一下。

  

 1 package java.util;
 2 
 3 /**
 4  * A class can implement the <code>Observer</code> interface when it
 5  * wants to be informed of changes in observable objects.
 6  *上面这句话翻译过来就是,当observable对象做出改变时,希望收到信息的类必须实现此接 
 7  * 口
 8  *
 9  */
10 public interface Observer {//观察者
11   //当observable对象状态改变时必须要调用此方法通知实现此接口的对象
12     void update(Observable o, Object arg);
13 }
14 
15 
16 package java.util;
17 
18 
19 public class Observable {//被观察者
20     private boolean changed = false;
21     private Vector<Observer> obs;//用来管理观察者的集合 怕线程不安全使用vector
22 
23     /** Construct an Observable with zero Observers. */
24 
25     public Observable() {
26         obs = new Vector<>();
27     }
28 
29    //添加观察者
30     public synchronized void addObserver(Observer o) {
31         if (o == null)
32             throw new NullPointerException();
33         if (!obs.contains(o)) {
34             obs.addElement(o);
35         }
36     }
37 
38    
39     public synchronized void deleteObserver(Observer o) {
40         obs.removeElement(o);
41     }
42 
43     
44    //通知观察者
45     public void notifyObservers() {
46         notifyObservers(null);
47     }
48 
49    
50     public void notifyObservers(Object arg) {
51       
52         Object[] arrLocal;
53 
54         synchronized (this) {
55        
56             if (!changed)//当被观察者状态没被改变 则终止此方法
57                 return;
58             arrLocal = obs.toArray();
59             clearChanged();
60         }
61 
62         for (int i = arrLocal.length-1; i>=0; i--)
63             ((Observer)arrLocal[i]).update(this, arg);//通知被观察者
64     }
65 
66   
67     public synchronized void deleteObservers() {
68         obs.removeAllElements();
69     }
70 
71  //改变被观察者状态
72     protected synchronized void setChanged() {
73         changed = true;
74     }
75 
76     
77     protected synchronized void clearChanged() {
78         changed = false;
79     }
80 
81    
82     public synchronized boolean hasChanged() {
83         return changed;
84     }
85 
86   
87     public synchronized int countObservers() {
88         return obs.size();
89     }
90 }

 

  用前些日子比较火的直播网站来举个例子,主播就是被观察者,观众则是观察者,观众们可以点击关注自己喜欢的主播(这里这个关注的动作就是观察者模式中的观察),当主播上线开始直播的时候,网站一般会通知观众们(通知)。以上场景用代码实现如下:

首先我们需要个主播,主播有自己的名字和直播的游戏,还有一个直播打游戏的方法。

 1 package com.java.pubsub;
 2 
 3 import java.util.Observable;
 4 
 5 public class Player extends Observable{
 6     
 7     public Player(String name){
 8         this.name = name;
 9         PlayerManage.getInstance().register(this);
10     }
11     
12     public void play(){
13         String title = "开播了,先"+this.game+"再吃鸡";
14         this.setChanged();
15         this.notifyObservers(title);
16     }
17     
18     private String name;
19     private String game;
20     public String getName() {
21         return name;
22     }
23     public void setName(String name) {
24         this.name = name;
25     }
26     public String getGame() {
27         return game;
28     }
29     public void setGame(String game) {
30         this.game = game;
31     }
32     
33     
34     
35 }

然后是我们的观众,我们的观众有关注主播和取消关注的两个方法之外,还有个提示主播上线打游戏的方法

 1 package com.java.pubsub;
 2 
 3 import java.util.Observable;
 4 import java.util.Observer;
 5 
 6 public class Viewer1 implements Observer{
 7     
 8     public void subscribe(String playerName){
 9         Player player = PlayerManage.getInstance().get(playerName);
10         if(player!=null){
11             player.addObserver(this);
12         }
13     }
14     
15     public void unsubscribe(String playerName){
16         Player player = PlayerManage.getInstance().get(playerName);
17         if(player!=null){
18             player.deleteObserver(this);
19         }
20     }
21     
22     
23     @Override
24     public void update(Observable o, Object arg) {
25         String title = (String) arg;
26         if(o instanceof Player){
27             Player player = (Player) o;
28             System.out.println("收到推送=="+player.getName()+":"+title);
29             System.out.println("我去看"+player.getName()+"直播"+player.getGame()+"游戏");
30         }
31     }
32 
33 }

在主播的代码和观众的代码中出现了个PlayerManage,主播那么多当然有个超管来管管了。。超管会在主播上线或者注册的时候开始管理主播(添加和获取),在主播播放不良内容后也可以封停主播(remove)

 1 package com.java.pubsub;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 public class PlayerManage {
 7     
 8     private Map<String,Player> playerMap = new <String,Player>HashMap();
 9     
10     public void register(Player player){
11         playerMap.put(player.getName(), player);
12     }
13     
14     public Player get(String playerName){
15         return playerMap.get(playerName);
16     }
17     
18     public void remove(Player player){
19         playerMap.remove(player.getName());
20     }
21     
22     private PlayerManage(){}
23     
24     public static PlayerManage getInstance(){
25         return PlayerManageInstance.manage;
26     }
27     
28     private static class PlayerManageInstance{//全站只有一个超管- - !
29         private static PlayerManage manage=new PlayerManage();
30     }
31 }

我们测试一下

 1 package com.java.pubsub;
 2 
 3 import java.util.Observable;
 4 
 5 public class Test {
 6     public static void main(String[] args) {
 7         Player player=new Player("张三");
 8         player.setGame("CS:GO");
 9         
10         Viewer1 viewer1=new Viewer1();
11         viewer1.subscribe("张三");
12         
13         player.play();
14         
15     }
16 }

结果为:

观察者模式分离了观察者和被观察者二者的责任,这样让类之间各自维护自己的功能,专注于自己的功能,会提高系统的可维护性和可重用性。

 总结一下,定义:观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。

  

posted @ 2018-04-12 22:52  最喜欢蕙蕙了  阅读(165)  评论(0编辑  收藏  举报