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

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

 

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

 

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

 

 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

(0)

相关推荐

  • 设计模式(19):中介者模式

    尺有所短,寸有所长;不忘初心,方得始终。 一、中介者模式是什么 【定义】 是用来降低多个对象和类之间的通信复杂性。通过一个中介类处理不同类之间的通信,并支持松耦合,使代码易于维护。…

    2022年8月17日
    00
  • 设计模式学习教程:解释器模式

    解释,一定是针对某种语言的拆解、释意,并按照文法翻译、转换成另一种表达形式以达到目标能够理解的目的。比如我们都知道java编程语言是人类可以理解的语言,程序写好后要先进行编译生成字…

    2022年5月7日
    00
  • 设计模式(14):策略模式

    「尺有所短,寸有所长;不忘初心,方得始终。」 一、策略模式是什么 策略模式「定义了一系列算法,并将每个算法封装起来,使他们可以在运行时相互替换,且算法的变化不会影响到使用算法的客户…

    2022年8月17日
    00
  • 设计模式学习教程:单例模式

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

    2022年5月7日
    00
  • 设计模式(8):适配器模式

    「尺有所短,寸有所长;不忘初心,方得始终。」 一、适配器模式是什么 适配器模式属于结构型模式,是作为两个不兼容的接口之间的桥梁,结合了两个独立接口的功能。 「主要作用」:将原本接口…

    2022年8月17日
    00
  • 设计模式(10):组合模式

    尺有所短,寸有所长;不忘初心,方得始终。 一、组合模式是什么 组合模式:又叫作整体-部分(Part-Whole)模式,它将对象组合成树状的层次结构,用来表示整体-部分的关系,使用户…

    2022年8月17日
    00
  • 设计模式(1):单例模式(Singleton Pattern)

    尺有所短,寸有所长;不忘初心,方得始终。 一、什么是单例模式 单例模式属于创建型模式,是 java 中最简单的设计模式之一,单例模式涉及到一个单一的类,该类负责创建自己的对象,同时…

    2022年8月17日
    00
  • 设计模式(12):外观模式

    “ 尺有所短,寸有所长;不忘初心,方得始终。 ” 一、外观模式是什么 外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易…

    2022年8月17日
    00
  • 设计模式(4):抽象工厂模式

    尺有所短,寸有所长;不忘初心,方得始终。 一、抽象工厂模式是什么 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。属于创建型模式,它提供了一种创建对象的…

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

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

    2022年8月17日
    00

发表回复

登录后才能评论