随处可见的观察者模式

2019-04-13 15:41发布

     最近在看《head first 设计模式》,有些模设比较难理解,比如策略模设,策略到底是什么策略呢?范围太广,很难想象。而观察者模设就挺容易理解的,观察者模设还有另一个名字“订阅者”模设,这个名字一听就清楚就明,因为订阅是日常生活中很常见的事,如订阅博客,订阅报纸,sns社交网络里的关注跟订阅有关;      那我们就先来看观察者模设的的定义是:对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。定义很清晰了,一下子就可以让我们联想到微薄上某个大V,更新一条微薄,所有的关注者都能收到它的通知并更新到自己的页面上。       我们先来看观察者的类图关系:        (图片其实来自《headfirst 设计模设》)     类图里该说的已经说的差不多了,那我们来看一下上面的类图写成一个报纸和订阅者的小程序是什么样子的:     先来看报纸的接口: public interface PaperInterface { //增加用户 public void attach(Subscriber sub); //删除用户 public void remove(Subscriber sub); //通知用户 public void notifySubscriber(News new); }
    下面是具体的报纸类,广州都市报 /** * 广州都市报 * @author asdzheng * */ public class GuangZhouPaper implements PaperInterface{ private List subs = new ArrayList(); @Override public void attach(Subscriber sub) { subs.add(sub); } @Override public void remove(Subscriber sub) { if(subs.contains(sub)) { subs.remove(sub); } else { System.out.println("你还没有订阅广州都市报,无法退订"); } } /** * 通知方法 */ @Override public void notifySubscriber(News new) { if(!subs.isEmpty()) { for(Subscriber sub : subs) { sub.update(new); } } else { System.out.println("没有订阅用户~"); } } public void noticeNewsChange(News new) { //这里可以轮巡访问广州都市报的新闻数据,如果发现有重大新闻,调用notifySubscriber() notifySubscriber(temp); } }
    下面是报纸里面的新闻,里面有重大新闻和广告:
public class News { private String importNews; private String ad; public News(String importNews, String ad) { this.importNews = importNews; this.ad = ad; } public String getImportNews() { return importNews; } public String getAd() { return ad; } }
上面是报纸和新闻,下来该来看看订阅
     订阅者接口: public interface Subscriber { //用户更新更新自己的状态 public void update(News new); }
      具体的订阅者Tom : /** * 用户Tom实现订阅接口 * @author asdzheng * */ public class Tom implements Subscriber{ public Tom(PaperInterface paper) { paper.attach(this); } @Override public void update(News new) { displayTodayNews(new); } public void displayTodayNews(News new) { System.out.println("Tom : 今天的重大新闻是 " + new.getImportNews()); } }
  具体的订阅者Lily: ** * 用户Lily实现订阅接口 * @author asdzheng * */ public class Lily implements Subscriber { public Lily(PaperInterface paper) { paper.attach(this); } @Override public void update(News new) { displayTodayAd(new); } public void displayTodayAd(News new) { System.out.println("Lily : 今天的广告是 " + new.getAd()); } }
看一下运行结果测试类:
public class ObserverTest { public static void main(String[] args) { GuangZhouPaper paper = new GuangZhowPaper(); Tom tom = new Tom(paper); Lily lily = new Lily(paper); paper.noticeNewsChange(new News("阿里上市马云成首付", "万科地产值得信赖")); } }
运行结果是: Tom : 今天的重大新闻是 阿里上市马云成首付  Lily : 今天的广告是 万科地产值得信赖
这个例子虽然简单,但可以看出观察者模设的脉络。不难看出Tom和Lily和新闻报纸是松耦合,它们只存在绑定和退订的关系,至于报纸从哪来,被和谐了什么,这些用户都可以不清楚也不应该清楚。松耦合是观察者模设的特性之一,能够应对变化,把对象的互相依赖降到最低。