zoukankan      html  css  js  c++  java
  • 公用技术——设计模式21——行为型模式——观察者模式

    1、概念

      观察者模式是将subject的动态通知给Observer。在程序上动态体现为内部状态的改变,即某个属性值发生改变。

      Subject与Observer应该抽象的去理解,而不是直接翻译它的英文。例如在直播平台中,Subject代表主播,而Observer代表用户。在微博中Subject代表微博用户,Observer也代表微博的用户,二者可以是同一类事物。

      观察者模式涉及到三种角色

    1. Subject,代表被订阅的,或被观察的事物。
    2. Platform:平台,建立Subject与Observer之间的关系,并管理它们。
    3. Observer:观察者,主动去订阅某些事物

      为了方便理解观察者模式,结合生活中的直播场景。当用户进入直播平台时,

    1. 用户浏览主播列表,发现自己的主播,点击关注,此时相当于用户与主播之间建立了订阅关系。
    2. 主播上线,或者展开什么活动,平台将主播的动态通知给用户,方式很多,站内信,短信,邮件等等。
    3. 用户不在喜欢该主播,取消关注,平台不在推送任何信息。此时用户与主播取消了订阅关系。

      抽象的理解三种角色,用户代表Observer,直播平台代表Platform,主播代表Subject。

      一层关系,订阅关系,点击关注,建立这种关系,点击取消关注,取消这种关系。

      在观察者模式中,我个人感觉Observer是主动方,是它在掌握着订阅关系的建立与取消,所以我感觉把addObserver,removeObserver的方法放入到Subject方法中不太合适。

    2、UML图

    3、代码

      User类,在直播场景中扮演着用户角色,在观察者模式中扮演着Observer角色,它是订阅关系的主动方。

    /**
     * 
     * @Title: User.java
     * @Package observer
     * @Description: 扮演着Observer的角色。
     * @version V1.0
     */
    public class User {
    	// 平台对象
    	private Platform platform;
    
    	public User(Platform platform) {
    		this.platform = platform;
    	}
        
    	// 在实际应用中表现为关联表中多添加一条记录
    	public void interestIn(Streamer streamer) {
    		platform.bindRelationShip(this,streamer);
    	}
    	
    	// 在实际应用中表现为关联表中少一条记录
    	public void canceliInterestIn(Streamer streamer) {
    		platform.unbindRelationShip(this,streamer);
    	}
    }
    

       Streamer类,在直播模型中扮演主播角色,在观察者模式中扮演Subject角色。

    public class Streamer {
    	// 平台对象
    	private Platform platform;
    	// 主播的唯一标识,房间号,ID,随意一个标识
    	private String id;
    
    	public Streamer(Platform platform) {
    		this.platform = platform;
    	}
    
    	/**
    	 * 
    	 * @Title: open
    	 * @Description: 主播开播了
    	 */
    	public void open() {
    		List<User> users = platform.selectUsersByStreamer(id);
    		for (User currentUser : users) {
    			// 以邮箱方式通知用户开播了
    			platform.notifyUser(currentUser, this.id + "已经开播了", NotifyMethod.EMAIL);
    		}
    	}
    
    	/**
    	 * 
    	 * @Title: close
    	 * @Description: 主播关闭直播了
    	 */
    	public void close() {
    		System.out.println("主播关闭了直播间");
    	}
    
    	/**
    	 * 
    	 * @Title: makeActivity
    	 * @Description: 主播发起了某个活动
    	 */
    	public void makeActivity() {
    		List<User> users = platform.selectUsersByStreamer(id);
    		for (User currentUser : users) {
    			// 以站内信的方式通知用户开播了
    			platform.notifyUser(currentUser, this.id + "正在发起某某活动,快来参与呀", NotifyMethod.INNER_MESSAGE);
    		}
    	}
    }
    

      Platform,在直播模型中扮演着平台的角色,在观察者模式中扮演着”平台”的角色,主要是管理和为订阅关系提供平台。当平台不复存在时,这种订阅关系随之消失。它并不是一个具体的类或者功能,这里只是需要这样一个角色,把所有的功能抽象到这个角色中。

    public class Platform {
    
    	/**
    	 * 
    	 * @Title: selectUsersByStreamer
    	 * @Description: 根据主播,查询所有关注他的用户
    	 * @param id
    	 * @return
    	 */
    	public List<User> selectUsersByStreamer(String id) {
    		// 有可能在数据库表中的关联表中执行一次查询
    		return null;
    	}
    
    	/**
    	 * 
    	 * @Title: notifyUser
    	 * @Description: 通知用户
    	 * @param user
    	 * @param string
    	 * @param method
    	 */
    	public void notifyUser(User user, String string, NotifyMethod method) {
    		switch (method) {
    			case EMAIL: {
    				// 发送邮件
    				break;
    			}
    			case INNER_MESSAGE: {
    				// 发送站内信
    				break;
    			}
    			case SHORT_MESSAGE_SERVICE: {
    				// 发送短信
    				break;
    			}
    		}
    	}
    
    	/**
    	 * 
    	 * @Title: bindRelationShip
    	 * @Description: 用户关注主播
    	 * @param user
    	 * @param streamer
    	 */
    	public void bindRelationShip(User user, Streamer streamer) {
    		// 有可能在数据库的关联表中添加一条记录
    	}
    
    	/**
    	 * 
    	 * @Title: unbindRelationShip
    	 * @Description: 用户取消关注主播
    	 * @param user
    	 * @param streamer
    	 */
    	public void unbindRelationShip(User user, Streamer streamer) {
    		// 有可能在数据库的关联表中删除一条记录
    	}
    }
    

      NotifyMethod,通知方式,是个枚举类

    public enum NotifyMethod {
    	/**
    	 * 站内信
    	 */
    	INNER_MESSAGE,
    	/**
    	 * 邮箱
    	 */
    	EMAIL,
    	/**
    	 * 短信
    	 */
    	SHORT_MESSAGE_SERVICE
    }
    

    4、讨论

      在观察者模式中,涉及到三种角色,Subject,Platform,Observer。

      涉及到两种关系,一种是Subject与Observer之间的1对多的关联关系。另外一种是Subject与Observer之间的订阅关系。很明显如果没有平台,订阅关系也失去了意义。

      涉及到三个问题,第一个问题是将哪些”动态”推送给Observer,第二个问题是推送的方式,短信,站内信,邮件等等,第三个问题是推送的频率,即when,何时推送,间隔周期,重复次数等等。

    5、示例

    • 求职者订阅求职网站的职位信息
    • 用户在直播平台关注喜欢的主播
    • 消费者在电商平台关注商品价格的动态
  • 相关阅读:
    C语言堆栈入门——堆和栈的区别
    Unity时钟定时器插件——Vision Timer源码分析之一
    UNITY3D 2D物流流体插件下载|Liquid Physics 2D
    Unity3d插件Master Audio AAA Sound v3.5
    游戏行业的女性拥有强大的新盟友:Facebook
    Unity游戏设计与实现 南梦宫一线程序员的开发实例
    Unity4.6证书激活问题
    里诺全系列注册机+暗桩patch
    冰点还原8.53破解版
    NSE: known a priori estimate
  • 原文地址:https://www.cnblogs.com/rain144576/p/9940850.html
Copyright © 2011-2022 走看看