设计模式学习教程:观察者模式

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

 

设计模式学习教程:观察者模式

 

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

 

 1public 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}

 

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

 

 1public class Buyer {// 买家
 2    private String name;// 买家姓名
 3    private Shop shop;// 商店引用
 4
 5    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行的购买行为中获取商品,最后是客户端类来模拟买家与商家的互动。

 

 1public 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);
 7
 8        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}

 

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

 

设计模式学习教程:观察者模式

 

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

 

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

 

 1public class Shop {
 2
 3    private String product;
 4    private List<Buyer> buyers;// 持有买家的引用
 5
 6    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方法,这是对各类形形色色买家的定制行为,故我们对买家类进行抽象如下。

 

 1public abstract class Buyer {
 2    protected String name;
 3    protected Shop shop;
 4
 5    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行注掉的代码,构造时强制将自己注册入商家名单,但为了灵活起见我们暂让买家自行决定是否注册。接下来我们来看众买家都是些什么样的人,首先是果粉买家。

 

 1public class PhoneFans extends Buyer {
 2
 3    public PhoneFans(String name, Shop shop) {
 4        super(name, shop);//调用父类进行构造
 5    }
 6
 7    @Override
 8    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行实现了父类抽象行为,接到通知后他做了逻辑判断,很明显这类买家只稀罕水果牌手机,别的商品不是他的菜。再来看另一类剁手党买家。

 

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

 

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

 

 1public 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);
 8
 9        //商店到货
10        shop.setProduct("猪肉炖粉条");
11        shop.setProduct("水果手机【爱疯叉】");
12
13        /*输出结果
14            剁手族八戒购买:猪肉炖粉条
15            果粉唐僧购买:水果手机【爱疯叉】
16            剁手族八戒购买:水果手机【爱疯叉】 
17        */
18    }
19}

 

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

 

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

 

设计模式学习教程:观察者模式

 

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/2453.html

(2)

及时掌握行业动态,欢迎加入几百人的后端技术交流群:


相关推荐

  • 设计模式学习教程:单例模式

    之前我们讲过面向对象以及封装、继承、多态三大特性,底子打好了那我们就把设计模式一个个拆开来看看到底都是神些什么鬼,我们先从简单的单例说起吧。单例,顾名思义,整个系统其实就只有一个实…

    2022年5月7日
    0052
  • 设计模式学习教程:中介模式

    中介,作用于多个事物之间充当交互沟通的媒介。我们的生活中有各种各样的媒介,比如一些传统媒体,书刊杂志,报纸,把信息传递给读者。再比如利用电子信息技术的互联网,作为一种新媒体,不单可…

    2022年5月7日
    0031
  • 设计模式(17):命令模式

    “ 尺有所短,寸有所长;不忘初心,方得始终。 一、命令模式是什么 【定义】:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。两者通过命令对象进行沟通,这样方便将命…

    2022年8月17日
    0073
  • 设计模式学习教程:命令模式

    命令模式,通常指的是一个对象向另一个对象发送信息指令的行为模型,比如父母命令孩子写作业、将军命令士兵进攻等。我们经过分析拆解方法会得到三个模块,首先得有命令发送方,接着是被传递的命…

    2022年5月7日
    0056
  • 设计模式(5):原型模式

    尺有所短,寸有所长;不忘初心,方得始终。 一、原型模式是什么 原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。统一…

    2022年8月17日
    0099
  • 设计模式学习教程:初探

    “世界处处不设计” 有物混成,先天地生。寂兮寥兮,独立而不改,周行而不殆,可以为天地母。吾不知其名,字之曰道,强为之名曰大。大曰逝,逝曰远,远曰反。 道是什么?道可道,非常道。道不…

    2022年5月7日
    0054
  • 设计模式(2):简单工厂模式

    尺有所短,寸有所长;不忘初心,方得始终。 简单工厂模式是属于创建型模式,又叫做静态工厂方法模式,但不属于23种设计模式之一。 简单工厂模式又称为静态工厂模式,实质是由一个工厂类根据…

    2022年8月17日
    1084
  • 设计模式(22):模板方法模式

    “ 尺有所短,寸有所长;不忘初心,方得始终。 一、模板方法模式是什么 “ 程序设计中:设计一个系统时知道了算法所需的关键步骤,确定步骤的执行顺序,但某些步骤的具体实现还未知,或者说…

    2022年8月17日
    0051
  • 设计模式(23):访问者模式

    「尺有所短,寸有所长;不忘初心,方得始终。」 一、访问者模式是什么 在我们日常生活中,经常会见到不同的角色针对相同的事务有着不同的处理方式,比如 树木在造纸厂中是纸的原材料,在建筑…

    2022年8月17日
    0062
  • 设计模式学习教程:代理模式

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

    2022年5月7日
    0039

发表回复

登录后才能评论