一:观察者模式简单介绍
观察者模式又称为发布-订阅模式(publish/subscribe),该模式定义了一种,一对多的依赖关系,让多个观察者同时监听一个主题对像,这个主题对像在状态发生改变时,会通知所有的观察者对像更新(执行业务逻辑)。示意图如下:
观察者角色介绍:
1:抽像主题角色(Subject)抽象主题角色是一个接口,把所有对观察者对象的引用保存在一个列表(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observer)角色。
2:具体主题角色(ConcreteSubject)具体主题是抽像主题接口实现类,用来管理观察者对像的增加,删除,通知。
3:抽像观察者角色(Observer)为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
4:具体观察者角色(ConcreteObserver)该类实现抽像观察者接口,最终业务逻辑代码的执行类。
二:观察者模式适用场景
1:当一个对象的数据更新时需要通知其他对象,但这个对象又不希望被通知的对象形成紧耦合
2:当一个对象的数据更新时,这个对象需要让其他对象也鸽子更新自己的数据,但这个对象不知道具体有多少对象需要更新数据
可能上面的描述比较抽像,我举一个例子,是去年我做电子商城项目用到的场景,商城有商品收藏,购物车等常用模块,这些模块都和商品价格有关,当时考虑到商品(商品数量:100000),用户(用户数量:100000)多了后,如果用户将所有商品都添加到购物车,所有商品添加到收藏列表,然后用户频繁去查询购物车列表,商品收藏列表,如果这两个操作都去关联商品表,肯定会导致查询慢, 所以我在购物车表,商品收藏表都保存了商品的主要属性(如:名称,价格等),在这种环境下,如果商品价格发生变动(如:联想电脑价格从5000涨到6000),购物车和收藏表价格肯定要跟着变化,如果不发生变化,商家和用户会找平台的麻烦,呵呵。不过目前和商品价格关联的只有这三张表,但后来商城增加了促销活动,比如抽奖,同样的道理,我也将商品主要属性(如:名称,价格)保存到了促销活动表,商城以后是否还有和商品价格相关的功能,我不知道,所以修改商品价格这个功能,观察者模式就派上了用场。具体代码如下:
代码清单一,抽像主题角色:
public interface IGoodsSubject { void attach(IGoodsObServer observer); void remove(IGoodsObServer observer); void notify(Goods bean); }
代码清单二,具体主题角色:
public class GoodsObserverWork implements IGoodsSubject { private List<IGoodsObServer> observerList = new ArrayList<IGoodsObServer>(); @Override public void attach(IGoodsObServer observer) { // TODO Auto-generated method stub observerList.add(observer); } @Override public void remove(IGoodsObServer observer) { // TODO Auto-generated method stub observerList.remove(observer); } @Override public void notify(Goods bean) { // TODO Auto-generated method stub for (IGoodsObServer observer : observerList) { observer.update(bean); } } }
代码清单三,抽像观察者角色:
public interface IGoodsObServer { boolean update(Goods goods); }
代码清单四,具体观察者角色:
//修改商品表价格 public class GoodsWork implements IGoodsObServer { @Override public boolean update(Goods goods) { // TODO Auto-generated method stub System.out.println("修改商品表价格"); return false; } } //修改购物车价格 public class ShoppingCartWork implements IGoodsObServer{ @Override public boolean update(Goods goods) { // TODO Auto-generated method stub System.out.println("修改购物车表的价格"); return false; } } //修改收藏列表价格 public class CollectionWork implements IGoodsObServer { @Override public boolean update(Goods goods) { // TODO Auto-generated method stub System.out.println("修改收藏表价格"); return false; } }
代码清单五,测试类:
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub IGoodsSubject goodsSubject = new GoodsObserverWork(); goodsSubject.attach(new GoodsWork()); goodsSubject.attach(new CollectionWork()); goodsSubject.attach(new ShoppingCartWork()); goodsSubject.notify(new Goods()); } }
后记:其实使用该模式的场景还有很多,比如用户注册成功,需要发邮件给用户,需要送用户积分等,不过在项目初期,就应该考虑到哪些模块,是否需要用到设计模式,这样才能更好的应用设计模式。