首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

观察者模式(公布-订阅)(转载含实例)

2013-08-13 
观察者模式(发布-订阅)(转载含实例)一、概述?Java 的设计模式很多,观察者模式被称为是模式中的皇后,而且Jav

观察者模式(发布-订阅)(转载含实例)

一、概述?
Java 的设计模式很多,观察者模式被称为是模式中的皇后,而且Java jdk也对它做了实现,可见该设计模式的重要位置。在图形化设计的软件中,为了实现视图和事件处理的分离,大多都采用了Observer模式,比如 Java的Swing,Flex的ActionScript等。在现实的应用系统中也有好多应用,比如像当当网、京东商城一类的电子商务网站,如果你对某 件商品比较关注,可以放到收藏架,那么当该商品降价时,系统给您发送站内消息、手机短信、邮件。这就是观察者模式的一个典型应用,商品是被观察者,关注该商品的客户 就是观察者。

GoF说道:Observer模式的意图是“定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”。参见下图:


观察者模式(公布-订阅)(转载含实例)

可以看出来,观察者模式,是一种一对多的关系,即多个观察者监听一个主题。

?

二、示例代码

商品价格打折后,所有关注、收藏该商品的用户都收到相关的信息提醒。

角色:

1)商品:被观察者;

2)用户:观察者

?

1.商品(发布者)

?

Java代码??观察者模式(公布-订阅)(转载含实例)
  1. import?java.util.ArrayList;????
  2. import?java.util.Iterator;????
  3. import?java.util.List;????
  4. ????
  5. /**??
  6. ?*?商品-发布者??
  7. ?*?@author?Administrator??
  8. ?*??
  9. ?*/????
  10. public?class?Product?{????
  11. ????private?String?name;????
  12. ????private?double?price;????
  13. ????private?List<Observer>?focusUsers;//观察者集合????
  14. ????????
  15. ????/**??
  16. ?????*?价格折扣??
  17. ?????*?@param?off??
  18. ?????*/????
  19. ????public?synchronized?void?payOff(double?off){????
  20. ????????this.price?=?getPrice()?*?(1?-?off);????????????
  21. ????????StringBuffer?msg?=?null;????
  22. ????????????
  23. ????????if(focusUsers?!=?null?&&?!focusUsers.isEmpty()){????
  24. ????????????Iterator?it?=?focusUsers.iterator();????
  25. ????????????while(it.hasNext()){????
  26. ????????????????Observer?user?=?(Observer)it.next();????
  27. ????????????????????
  28. ????????????????String?msgPart?=?",?"+?this.getName()?+"的价格?"+?this.getPrice()?+",?价格折扣?"+?off?*?100?+"%!";????
  29. ????????????????msg?=?new?StringBuffer();????
  30. ????????????????msg.append("~~~~?您好?"+?user.getName());????
  31. ????????????????msg.append(msgPart);????
  32. ????????????????????
  33. ????????????????user.notify(msg.toString());//发送提醒????
  34. ????????????}????
  35. ????????}????
  36. ????}????
  37. ????????
  38. ????/**??
  39. ?????*?添加关注用户??
  40. ?????*?@param?user??
  41. ?????*/????
  42. ????public?void?addFocusUsers(User?user)?{????
  43. ????????this.getFocusUsers().add(user);????
  44. ????}????
  45. ????/**??
  46. ?????*?删除关注用户??
  47. ?????*?@param?user??
  48. ?????*/????
  49. ????public?void?delFocusUser(User?user)?{????
  50. ????????this.getFocusUsers().remove(user);????
  51. ????}????
  52. ????????
  53. ????????
  54. ????public?Product(){????
  55. ????????focusUsers?=?new?ArrayList<Observer>();????
  56. ????}????
  57. ????????
  58. ????public?String?getName()?{????
  59. ????????return?name;????
  60. ????}????
  61. ????public?void?setName(String?name)?{????
  62. ????????this.name?=?name;????
  63. ????}????
  64. ????public?double?getPrice()?{????
  65. ????????return?price;????
  66. ????}????
  67. ????public?void?setPrice(double?price)?{????
  68. ????????this.price?=?price;????
  69. ????}????
  70. ????????
  71. ????????
  72. ????public?List<Observer>?getFocusUsers()?{????
  73. ????????return?focusUsers;????
  74. ????}????
  75. ????public?void?setFocusUsers(List<Observer>?focusUsers)?{????
  76. ????????this.focusUsers?=?focusUsers;????
  77. ????}????
  78. ????????
  79. }????

?

?

2.观察者(订阅者)接口

?

Java代码??观察者模式(公布-订阅)(转载含实例)
  1. /**??
  2. ?*?观察者(订阅者)接口??
  3. ?*?@author?Administrator??
  4. ?*??
  5. ?*/????
  6. public?interface?Observer?{????
  7. ????????
  8. ????public?void?notify(String?msg);????
  9. ????????
  10. ????public?String?getName();????
  11. ????????
  12. }????

?

?

3.观察者(订阅者)

?

Java代码??观察者模式(公布-订阅)(转载含实例)
  1. import?java.util.HashSet;????
  2. import?java.util.Set;????
  3. ????
  4. /**??
  5. ?*?观察者(订阅者)??
  6. ?*?@author?Administrator??
  7. ?*??
  8. ?*/????
  9. public?class?User?implements?Observer?{????
  10. ????private?String?name;????
  11. ????private?Set<Product>?focusPdts;????
  12. ????????
  13. ????/**??
  14. ?????*?通知方法??
  15. ?????*/????
  16. ????public?void?notify(String?msg){????
  17. ????????System.out.println(msg);????
  18. ????}????
  19. ????????
  20. ????public?User(){????
  21. ????????focusPdts?=?new?HashSet<Product>();????
  22. ????}????
  23. ????????
  24. ????public?String?getName()?{????
  25. ????????return?name;????
  26. ????}????
  27. ????public?void?setName(String?name)?{????
  28. ????????this.name?=?name;????
  29. ????}????
  30. ????public?Set<Product>?getFocusPdts()?{????
  31. ????????return?focusPdts;????
  32. ????}????
  33. ????public?void?setFocusPdts(Set<Product>?focusPdts)?{????
  34. ????????this.focusPdts?=?focusPdts;????
  35. ????}???????
  36. ????????
  37. }???

?

?

4.client端调用

?

Java代码??观察者模式(公布-订阅)(转载含实例)
  1. public?class?client?{????
  2. ????
  3. ????/**??
  4. ?????*?@param?args??
  5. ?????*/????
  6. ????public?static?void?main(String[]?args)?{????
  7. ????????//产品????
  8. ????????Product?mobile?=?new?Product();????
  9. ????????mobile.setName("SAMSUNG手机");????
  10. ????????mobile.setPrice(2000);????
  11. ????????????
  12. ????????Product?book?=?new?Product();????
  13. ????????book.setName("JAVA设计模式");????
  14. ????????book.setPrice(80);????
  15. ????????????
  16. ????????//用户????
  17. ????????User?user1?=?new?User();????
  18. ????????user1.setName("张三");????
  19. ????????user1.getFocusPdts().add(mobile);//关注某一款三星手机????
  20. ????????//user1.getFocusPdts().add(book);//关注JAVA设计模式????
  21. ????????????
  22. ????????User?user2?=?new?User();????
  23. ????????user2.setName("李四");????
  24. ????????user2.getFocusPdts().add(mobile);//关注某一款三星手机????
  25. ????????user2.getFocusPdts().add(book);//关注JAVA设计模式????
  26. ????????????
  27. ????????//建立商品和订阅者关联????
  28. ????????mobile.getFocusUsers().add(user1);????
  29. ????????book.getFocusUsers().add(user1);????
  30. ????????book.getFocusUsers().add(user2);????
  31. ????????????
  32. ????????//产品打折,发送站内信提醒????
  33. ????????mobile.payOff(0.1);????
  34. ????????book.payOff(0.2);????
  35. ????}????
  36. ????
  37. }????

?

?

三、功能设计

常用的处理方式:

将数据库作为数据存储的介质,消息提醒数据保存在数据库表中,采用定时任务的方式来汇总和发送。具体流程:

1.存储用户-关注关联数据

将用户和所关注的数据存储到一张“用户-关注商品关联表”;

?

2.执行汇总任务

商品打折时,触发汇总任务,遍历“用户-关注商品“关联表,将符合发送条件的记录汇总到”提醒消息表“;数据量巨大的情况下,可采用在“用户-关注商品关联表”冗余字段的方式,不再创建”提醒消息表“减小数据量。

?

3.发送折扣提醒消息

遍历”提醒消息表“并发送,发送完成后,将记录标示为已发送。

?

四、设计分析

如果系统的用户、商品数量都很大,这种情况下如何设计功能更合理呢,个人认为有几点需要关注:

1)响应及时性

2)数据的持久性

3)web层压力

4)数据库层压力

5)系统资源的消耗

?

内存方式:?? 采用观察者模式,将关注用户保存在商品对象中,也就是存储在java 堆中。

数据库方式:采用传统关系型数据,例如mysql等。

?

?

项目

内存

数据库

分析

内存方式,对系统内存占用较大,但对其他系统资源消耗不大。数据库方式,对系统的数据库层有较大的压力。

?

通过以上分析,发现两种方式都有比较大的问题,那是否可以采用key-value型内存软件加持久数据到数据库中的方式来实现呢?

1)key-value型内存操作比直接数据库操作(磁盘io)操作性能上好很多;
2)将内存数据保存1份到数据库应对内存失效问题,采用异步持久化方式可减小对系统整体资源的消耗。原帖地址:http://qify.iteye.com/blog/1921919?附件为本人自己写的小例子

热点排行