由于网站带有弱sns功能,因此需要设计关注和被关注的消息或是动作通知,那么将这个需求抽象出来的时候就会发现正好符合java中发布订阅模式。
一、概述
Java 的设计模式很多,观察者模式被称为是模式中的皇后,而且Java jdk也对它做了实现,可见该设计模式的重要位置。在图形化设计的软件中,为了实现视图和事件处理的分离,大多都采用了Observer模式,比如 Java的Swing,Flex的ActionScript等。在现实的应用系统中也有好多应用,比如像当当网、京东商城一类的电子商务网站,如果你对某 件商品比较关注,可以放到收藏架,那么当该商品降价时,系统给您发送站内消息、手机短信、邮件。这就是观察者模式的一个典型应用,商品是被观察者,关注该商品的客户 就是观察者。
GoF说道:Observer模式的意图是“定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”。参见下图:
可以看出来,观察者模式,是一种一对多的关系,即多个观察者监听一个主题。
二、示例代码
商品价格打折后,所有关注、收藏该商品的用户都收到相关的信息提醒。
角色:
1)商品:被观察者;
2)用户:观察者
1.商品(发布者)
import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 商品-发布者 * @author Administrator * */ public class Product { private String name; private double price; private List<Observer> focusUsers;//观察者集合 /** * 价格折扣 * @param off */ public synchronized void payOff(double off){ this.price = getPrice() * (1 - off); StringBuffer msg = null; if(focusUsers != null && !focusUsers.isEmpty()){ Iterator it = focusUsers.iterator(); while(it.hasNext()){ Observer user = (Observer)it.next(); String msgPart = ", "+ this.getName() +"的价格 "+ this.getPrice() +", 价格折扣 "+ off * 100 +"%!"; msg = new StringBuffer(); msg.append("~~~~ 您好 "+ user.getName()); msg.append(msgPart); user.notify(msg.toString());//发送提醒 } } } /** * 添加关注用户 * @param user */ public void addFocusUsers(User user) { this.getFocusUsers().add(user); } /** * 删除关注用户 * @param user */ public void delFocusUser(User user) { this.getFocusUsers().remove(user); } public Product(){ focusUsers = new ArrayList<Observer>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public List<Observer> getFocusUsers() { return focusUsers; } public void setFocusUsers(List<Observer> focusUsers) { this.focusUsers = focusUsers; } }
2.观察者(订阅者)接口
/** * 观察者(订阅者)接口 * @author Administrator * */ public interface Observer { public void notify(String msg); public String getName(); }
3.观察者(订阅者)
import java.util.HashSet; import java.util.Set; /** * 观察者(订阅者) * @author Administrator * */ public class User implements Observer { private String name; private Set<Product> focusPdts; /** * 通知方法 */ public void notify(String msg){ System.out.println(msg); } public User(){ focusPdts = new HashSet<Product>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Product> getFocusPdts() { return focusPdts; } public void setFocusPdts(Set<Product> focusPdts) { this.focusPdts = focusPdts; } }
4.client端调用
public class client { /** * @param args */ public static void main(String[] args) { //产品 Product mobile = new Product(); mobile.setName("SAMSUNG手机"); mobile.setPrice(2000); Product book = new Product(); book.setName("JAVA设计模式"); book.setPrice(80); //用户 User user1 = new User(); user1.setName("张三"); user1.getFocusPdts().add(mobile);//关注某一款三星手机 //user1.getFocusPdts().add(book);//关注JAVA设计模式 User user2 = new User(); user2.setName("李四"); user2.getFocusPdts().add(mobile);//关注某一款三星手机 user2.getFocusPdts().add(book);//关注JAVA设计模式 //建立商品和订阅者关联 mobile.getFocusUsers().add(user1); book.getFocusUsers().add(user1); book.getFocusUsers().add(user2); //产品打折,发送站内信提醒 mobile.payOff(0.1); book.payOff(0.2); } }
三、功能设计
常用的处理方式:
将数据库作为数据存储的介质,消息提醒数据保存在数据库表中,采用定时任务的方式来汇总和发送。具体流程:
1.存储用户-关注关联数据
将用户和所关注的数据存储到一张“用户-关注商品关联表”;
2.执行汇总任务
商品打折时,触发汇总任务,遍历“用户-关注商品“关联表,将符合发送条件的记录汇总到”提醒消息表“;数据量巨大的情况下,可采用在“用户-关注商品关联表”冗余字段的方式,不再创建”提醒消息表“减小数据量。
3.发送折扣提醒消息
遍历”提醒消息表“并发送,发送完成后,将记录标示为已发送。
四、设计分析
如果系统的用户、商品数量都很大,这种情况下如何设计功能更合理呢,个人认为有几点需要关注:
1)响应及时性
2)数据的持久性
3)web层压力
4)数据库层压力
5)系统资源的消耗
内存方式: 采用观察者模式,将关注用户保存在商品对象中,也就是存储在java 堆中。
数据库方式:采用传统关系型数据,例如mysql等。
项目 |
内存 |
数据库 |
分析 |
响应及时性 |
较好 |
较差 |
内存操作比起数据库操作肯定性能上好很多 |
数据的持久性 |
较差 |
较好 |
如果出现宕机等故障,内存数据会被清空,导致整个功能异常。 所以说数据仅保存在内存有缺陷,将内存数据持久化到数据库中做备份是较完备的方案,具体实现暂不讨论。 |
web层压力 |
较大 |
中等 |
由于用户和商品数量巨大,商品-内存关联数据保存在内存中对系统内存消耗较大,假如1000W用户,每个用户关注10个商品的话,每条记录100Byte,那么大致占用10G左右,直觉上对内存占用较大,会影响整个系统的表现。 |
数据库层压力 |
无 |
较大 |
用户-商品关注关联表,约1亿条数据。发送提醒消息和更改发送标示需要1次读操作、1次写操作,对数据的存储和数据库的压力都是一个挑战。另外,实现上肯定要采用缩小每次读写操作的数据集的方式。 |
系统资源消耗 |
中等 |
中等 |
内存方式,对系统内存占用较大,但对其他系统资源消耗不大。数据库方式,对系统的数据库层有较大的压力。 |
通过以上分析,发现两种方式都有比较大的问题,那是否可以采用key-value型内存软件加持久数据到数据库中的方式来实现呢?
2)将内存数据保存1份到数据库应对内存失效问题,采用异步持久化方式可减小对系统整体资源的消耗。
相关推荐
改demo主要叙述java版本发布预订阅模式的主导思想(观察者模式)
NULL 博文链接:https://wb284551926.iteye.com/blog/1923535
Android设计模式--观察者模式DEMO 观察者模式是一个使用频率非常高的模式,他最常用的地方是GUI系统和订阅-发布系统。 该模式的最重要的作用就是解耦,使观察者和被观察者之间依赖尽可能小,甚至好无依赖。
主要介绍了JavaScript设计模式之观察者模式(发布者-订阅者模式),本文详细的讲解了JavaScript中的观察者模式,需要的朋友可以参考下
本文实例讲述了JavaScript设计模式之观察者模式与发布订阅模式。分享给大家供大家参考,具体如下: 学习了一段时间设计模式,当学到观察者模式和发布订阅模式的时候遇到了很大的问题,这两个模式有点类似,有点傻傻...
观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件...
利用观察者模式(发布/订阅模式)制作一个“代替”广播的通知类
Observer (观察者模式) 又叫做发布/订阅(Publish/Subscribe)模式。 当一个对象的改变同时会影响其他对象的行为的时候,可以使用此设计模式。 l 主题对象 :一个需要被关注的主题对象,这个主题对象改变会影响...
观察者设计模式观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时...
c++设计模式-行为型模式-观察者模式;qt工程;c++简单源码; 观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式...
在设计一组依赖的对象与它们所依赖的对象之间一致(同步)的交流模型时,观察者模式(Observer Pattern)很有用。它可以使依赖对象的状态与它们所依赖的对象的状态保持同步。这组依赖的对象指的是观察者(Observer)...
主要介绍了JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法,结合实例形式分析了JavaScript观察者模式概念、原理、使用方法及相关操作注意事项,需要的朋友可以参考下
该资源是C#不同窗体间的数据传递发布订阅模式(观察者模式)源码范例,资源很好,思路清晰,值得大家借鉴
观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件...
观察者模式通常的叫法叫做订阅-发布模式,类似于报刊杂志的订阅,观察者和被观察者就是读者和邮局的关系,读者先要在邮局订阅想要的报刊,当报刊发行时,邮局会将报刊邮寄到读者家里。观察者(Observer)和被观察者...
对应的博客链接:http://blog.csdn.net/t1234xy4/article/details/52432559#