zoukankan      html  css  js  c++  java
  • 项目中用到的设计模式-观察者模式

    一:观察者模式简单介绍

      观察者模式又称为发布-订阅模式(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());
        }
    }

    后记:其实使用该模式的场景还有很多,比如用户注册成功,需要发邮件给用户,需要送用户积分等,不过在项目初期,就应该考虑到哪些模块,是否需要用到设计模式,这样才能更好的应用设计模式。

      

  • 相关阅读:
    在工作中你可能会遇见的事情哈
    原生js判断某个区域的滚动条滚动到了底部
    震惊p div 标签 可以编辑高度随内容的编辑而发生变化
    Codeforces Round #628 (Div. 2) B. CopyCopyCopyCopyCopy(Set)
    Codeforces Round #628 (Div. 2) A. EhAb AnD gCd(LCM & GCD)
    Codeforces Round #613 (Div. 2) C. Fadi and LCM(LCM & GCD)
    Codeforces Round #613 (Div. 2) B. Just Eat It!(前缀和)
    Codeforces Round #613 (Div. 2) A. Mezo Playing Zoma(逻辑)
    GPLT L2-006 树的遍历(二叉树)
    poj 3278 Catch That Cow(记忆化广度优先搜索)
  • 原文地址:https://www.cnblogs.com/cq-jiang/p/7732547.html
Copyright © 2011-2022 走看看