• 设计模式之观察者模式


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

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

            

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

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

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

      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 }

    结果为:

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

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

      

  • 相关阅读:
    WPF添加ResourceDictionary后【The Property "Resource" can only be set once】问题
    WPF中获取匿名(Anonymous)对象的键值方法(例如DataGrid绑定List<无名元素>时)
    安装Win10到移动硬盘的利器:WTGA
    xcodebuild 能在模拟器上运行测试啦
    Jenkins Mac slave 遇到 git: 'credential-osxkeychain' is not a git command. 错误
    远程调试UWP遇到新错误Could not generate the root folder for app package ......
    开始学习python
    文件打包
    统计 某个目录下 所有的文件的行数
    根据进程名称获取进程id
  • 原文地址:https://www.cnblogs.com/loveyejinhui/p/8811014.html
Copyright © 2020-2023  润新知