眼观六路,耳听八方,观察者很忙,随时监控着关注对象的一举一动。记者、摄影师、重症监护的护士,被套的股民,无不为了完成任务疲于奔命,而观察者模式正是为了解决这个问题而诞生。

观察者的痛点到底在哪里呢?让我们用购物来做例程,假设某件商品(水果手机)卖得非常火爆,长期处于脱销的状态。由于供不应求,师徒四人也加入了抢购的队伍,不时的去商店询问是否有货,先看商店类代码。

 1 public class Shop {2    private String product;//商品3    //初始商店无货4    public Shop() {5        this.product = "无商品";6    }7    //商店出货8    public String getProduct() {9        return product;
10    }
11    //商店进货
12    public void setProduct(String product) {
13        this.product = product;
14    }
15 }

简单易懂,然后是买家类,充当观察者角色。

 1 public class Buyer {// 买家2    private String name;// 买家姓名3    private Shop shop;// 商店引用45    public Buyer(String name, Shop shop) {6        this.name = name;7        this.shop = shop;8    }9
10    public void buy() {// 买家购买商品
11        System.out.print(name + "购买:");
12        System.out.println(shop.getProduct());
13    }
14 }

注意第3行买家持有商店的引用,用来在第10行的购买行为中获取商品,最后是客户端类来模拟买家与商家的互动。

 1 public class Client {2    public static void main(String[] args) {3        Shop shop = new Shop();4        Buyer wukong = new Buyer("悟空", shop);5        Buyer shaseng = new Buyer("沙僧", shop);6        Buyer bajie = new Buyer("八戒", shop);78        wukong.buy();// 悟空购买:无商品9        bajie.buy();// 八戒购买:无商品
10        shaseng.buy();// 沙僧购买:无商品
11        bajie.buy();// 八戒购买:无商品
12
13        // 师傅忍不住了,也加入了购买行列。
14        Buyer tangseng = new Buyer("唐僧", shop);
15        tangseng.buy();// 唐僧购买:无商品
16
17        // 除了八戒其他人都放弃了
18        bajie.buy();// 八戒购买:无商品
19        bajie.buy();// 八戒购买:无商品
20
21        // 商店终于进货了
22        shop.setProduct("最新旗舰手机");
23        bajie.buy();// 八戒购买:最新旗舰手机
24    }
25 }

看到这些买家的疯狂行为没有?一开始师傅命三位徒弟去抢购,商店一直处于无货状态,师傅坐立难安,也加入了抢购大军,最终徒儿刚鬣脱颖而出,终于抢到了梦寐以求的手机,整个过程堪比九九八十一难。

大家有没有发现问题?除了最后一步目的达成之外,之前的部分都是在做无用功,并且此处代码只是模拟了师徒四人而已,真实情况并非如此简单,可能会有成千上万的疯狂粉丝不断询问有没有到货,商家的店员可能会被逼疯。

到这里大家肯定已经想到了,与其让观察者不断的询问不如当到货的时候让商家主动通知观察者们来买吧,换个角度分析问题马上迎刃而解,醍醐灌顶般清爽,开始设计优雅观察者的模式,首先从商家类开始重构。

 1 public class Shop {23    private String product;4    private List<Buyer> buyers;// 持有买家的引用56    public Shop() {7        this.product = "无商品";8        this.buyers = new ArrayList<>();9    }
10
11    // 为了主动通知买家,买家得来店里注册。
12    public void register(Buyer buyer) {
13        this.buyers.add(buyer);
14    }
15
16    public String getProduct() {
17        return product;
18    }
19
20    public void setProduct(String product) {
21        this.product = product;// 到货了
22        notifyBuyers();// 到货后通知买家
23    }
24
25    // 通知所有注册买家
26    public void notifyBuyers() {
27        buyers.stream().forEach(b -> b.inform());
28    }
29 }

注意第12行的注册方法,所有关注商品的买家都应先注册(订阅),比如告知商家手机号以便第20行到货后可以接到通知,以及第26行的通知方法对所有买家进行迭代,并调用买家的inform进行告知。所以这里我们规定,对于Buyer买家必须要有inform方法,这是对各类形形色色买家的定制行为,故我们对买家类进行抽象如下。

 1 public abstract class Buyer {2    protected String name;3    protected Shop shop;45    public Buyer(String name, Shop shop) {6        this.name = name;7        this.shop = shop;8 //        shop.register(this);9    }
10
11    public abstract void inform();
12
13 }

很简单,我们对买家进行了抽象,其中第11行inform方法必须得到实现,通知到你了怎样处理自己看着办咯。注意第8行注掉的代码,构造时强制将自己注册入商家名单,但为了灵活起见我们暂让买家自行决定是否注册。接下来我们来看众买家都是些什么样的人,首先是果粉买家。

 1 public class PhoneFans extends Buyer {23    public PhoneFans(String name, Shop shop) {4        super(name, shop);//调用父类进行构造5    }67    @Override8    public void inform() {9        String product = shop.getProduct();
10        if(product.contains("水果手机")){//此买家只买水果牌手机
11            System.out.print(name);
12            System.out.println("购买:" + product);
13        }
14    }
15 }

买家的行为各式各样,在第8行实现了父类抽象行为,接到通知后他做了逻辑判断,很明显这类买家只稀罕水果牌手机,别的商品不是他的菜。再来看另一类剁手党买家。

 1 public class HandChopper extends Buyer {23    public HandChopper(String name, Shop shop) {4        super(name, shop);5    }67    @Override8    public void inform() {9        System.out.print(name);
10        String product = shop.getProduct();
11        System.out.println("购买:" + product);
12    }
13 }

与果粉不同,他是来者不拒,只要有货就买买买!最后来看客户端的神操作。

 1 public class Client {2    public static void main(String[] args) {3        Shop shop = new Shop();4        Buyer tanSir = new PhoneFans("果粉唐僧", shop);5        Buyer barJeet = new HandChopper("剁手族八戒", shop);6        shop.register(tanSir);7        shop.register(barJeet);89        //商店到货
10        shop.setProduct("猪肉炖粉条");
11        shop.setProduct("水果手机【爱疯叉】");
12
13        /*输出结果
14            剁手族八戒购买:猪肉炖粉条
15            果粉唐僧购买:水果手机【爱疯叉】
16            剁手族八戒购买:水果手机【爱疯叉】
17        */
18    }
19 }

无与伦比地优雅,第6行开始对疯狂买家师徒二人进行注册,于是他们再也不见他们终日徘徊于店门之外苦苦等待的身影了。接下来某日商店到货(第10行),至此购买过程就这样神奇地结束了,不信?看输出结果,嗯,不单买家很奇葩,连店都很奇葩。总之,商家只要到货就会马上打电话给这些订阅买家告知可以购买了。

其实,最初商家与买家之间的互动行为非常类似于Web应用中的Poll行为,由于Http无状态连接协议的安全特性,服务端(商家)无法主动推送(Push)消息给客户端(买家),所以有时会用到Poll技术,也就是不断的轮询服务端,有没有更新?有没有更新?有没有更新?严重时,成千上万的客户端会造成服务器瘫痪,所以之后诞生的WebSocket正是为了解决这个问题,这便类似于我们的观察者模式。

观察者模式解决了基于一对多对象结构关系间的互动问题,使观察者(多方买家)专主动为被动,被观察者(单方商家)转被动为主动,此情此景,需动静结合,先后有序,以【一方动多方静】取代【多方动一方静】的模式,大大的提高了沟通效率,别再偷窥了,我show给你好看。

JAVA设计模式什么鬼(观察者)——作者:凸凹里歐相关推荐

  1. JAVA设计模式什么鬼(备忘录)——作者:凸凹里歐

    备忘录,备份曾经发生过的历史记录,以防忘记,之后便可以轻松回溯过往.想必我们曾经都干过很多蠢事导致糟糕的结果,当后悔莫及的时候已经是覆水难收了,只可惜这世界上没有后悔药,事后我们能做的只能去弥补过失, ...

  2. JAVA设计模式什么鬼(策略)——作者:凸凹里歐

    策略,Strategy,古时也称"计",为了达成某个目标的方案,目标不同,方案也随之更改.例如特工执行任务时总要准备好几套方案以应对突如其来的变化,A计划实施过程中情况突变导致预案 ...

  3. JAVA设计模式什么鬼(状态)——作者:凸凹里歐

    状态State,指某事物所处的状况或形态,比如水的三态,零下会变成固态冰,常温会是液态水,100℃会蒸发成气态的水蒸气. 在这个地球生态系统中,水的总量并不会增加,也不会减少,只是随着温度的变化其分子 ...

  4. JAVA设计模式什么鬼(代理)——作者:凸凹里歐

    代理,代表打理,以他人的名义代表委托人打理其本职工作之外或不所能及的事务,达成合作关系并更高效地促成事务完成的目的.例如明星经纪人,他们并没有像明星一样会唱歌.跳舞或演戏,而是替明星打理一些无暇顾及的 ...

  5. JAVA设计模式什么鬼(初探)——作者:凸凹里歐

    有物混成,先天地生.寂兮寥兮,独立而不改,周行而不殆,可以为天地母.吾不知其名,字之曰道,强为之名曰大.大曰逝,逝曰远,远曰反. 道是什么?道可道,非常道.道不明,说不尽的才算是道,它是自然法则的终极 ...

  6. JAVA设计模式什么鬼(适配器)——作者:凸凹里歐

    我们这个世界,充满着千奇百怪的对象,更有趣的是对象与对象间是存在着互动,沟通,这样世界才变得美妙.那到底是怎样互动呢?靠什么才能互动呢?是的,接口.比如你和朋友一起喝茶聊天,我们暂且不管声带,耳膜这些 ...

  7. JAVA设计模式什么鬼(装饰)——作者:凸凹里歐

    装饰,在某物件基础上加以修饰,装点,使得原本的朴素变得华丽,达到化腐朽为神奇的效果.比如我们从开发商买来的毛坯房,必然要进行室内装潢这么一项工程,什么简约风啊,北欧风啊,地中海,美式中式等等,当然萝卜 ...

  8. JAVA设计模式什么鬼(模板方法)——作者:凸凹里歐

    面向对象,是对事物属性与行为的封装,方法,指的就是行为.模板方法,显而易见是说某个方法充当了模板的作用,其充分利用了抽象类虚实结合的特性,虚部抽象预留,实部固定延续,以达到将某种固有行为延续至子类的目 ...

  9. JAVA设计模式什么鬼(门面)——作者:凸凹里歐

    开门见山,门,建筑物的入口,面,脸也.门面(Facade),通常指店铺的门头外表部分,当然一定要临街才是好的商铺,在人流量大的地方营造更好的视觉冲击,这样会有更多等等机会暴露给潜在顾客,否则只能是靠& ...

最新文章

  1. 【每日一算法】单词接龙
  2. unix编程艺术的设计原则
  3. PC-lint 的代码实例
  4. hashmap 遍历_这21个刁钻的HashMap面试题,我把阿里面试官吊打了
  5. POI文件导入:需求说明
  6. how to replace the note reuse project into my own one
  7. java类型转换造成的字节丢失,java 编码转换(已解决,转换字节丢失,无法实现)
  8. Hibernate使用原生SQL适应复杂数据查询
  9. NVLink技术及影响解析
  10. 查询手机号段对应地区编码_2020陕西专升本考试今日起查询成绩啦
  11. javascript基本数据类型与值类型引用类型说明
  12. 苹果又发布一个机器学习框架,帮自家生态里的开发者降低AI门槛
  13. 破解版超级数据恢复软件-内含已破解注册码
  14. python实现【国家统计局】三级区划代码和城乡划分代码爬取
  15. 光猫需要已经开通了 telnet 功能
  16. 计算机硬盘序列号是空白,为什么小弟我的获取硬盘序列号的代码,在有些电脑下没法获取到硬盘序列号,即返回值为空白...
  17. i2c驱动之at24c08(1)
  18. hbase 二级索引方案
  19. 面向未来的大数据核心技术都有什么?
  20. Java用OpenOffice将word转换为PDF并预览

热门文章

  1. 微信跳一跳辅助脚本(神奇的战士版本)安装过程的各种问题合集(附教程连接)
  2. 闲暇时,写的一个Qt简单桌面日程工具
  3. Android 导出.vcf格式通讯录方法
  4. git快速入门-笔记(MD格式)
  5. 鲁棒优化入门(二)——基于matlab+yalmip求解鲁棒优化问题
  6. Java设计模式--在项目中的应用
  7. BC26通过LWM2M接入电信AEP平台(非透传模式 Json格式)
  8. python下载显示文件丢失连不上网_python39.dll文件下载,金山毒霸dll修复工具帮您解决文件丢失导致“python39.dll找不到”的系统问题...
  9. b360i能用的黑苹果网卡_安装i7-8700+微星 B360M MORTAR+GTX 1060 黑苹果Hackintosh
  10. css中 中文字体(font-family)的标准英文名称