行为型模式:观察者模式。

行为型模式:观察者模式java

灯塔

十一大行为型模式之七:观察者模式。设计模式

简介

姓名 :观察者模式
英文名 :Observer Pattern
价值观 :盯着你怎么着
我的介绍
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则全部依赖于它的对象都会获得通知并被自动更新。
(来自《设计模式之禅》)微信

你要的故事

想来想去,就拿咱们如今生活中最常体会到的事情来说观察者模式--朋友圈。小明、小红、小东 3 人是好朋友,最近他们的父母都给安排了手机,刚用上手机那是至关的兴奋呀。他们立马从 QQ 转投到微信的怀抱,对微信的朋友圈玩的不亦乐乎,什么事情都往上面发。忽然有一天,小明和小红由于一些小事争执闹别扭了,缘由就是他们对一道数学题有不一样的看法。就跟咱们小时候和朋友玩得好好的,忽然由于一点小事就闹翻了。小红比较孩子气,立马就屏蔽了小明的朋友圈,不想再看到有关小明相关的信息。故事就是这么一回事,关注点就在这朋友圈上。朋友圈就是运用观察者模式的一个很好的样例。为何这么说?咱们发朋友圈的时候,那些没有屏蔽咱们朋友圈的好友,会收到信息推送。也就是没有屏蔽咱们朋友圈的好友实际上是订阅了咱们朋友圈,好友至关于观察者,咱们是被观察的对象。符合观察者模式这个关系。ide

咱们经过代码来描述小明、小红、小东他们在朋友圈玩的场景。利用观察者模式,须要观察对象和被观察对象,因此咱们先定义 2 个接口,分别是 Observable (可被观察接口) 和 Observer (观察者接口)。学习

实现 Observable 接口的对象说明是可被订阅观察的,因此它须要 addObserver() 新增订阅者方法和 removeObserver() 移除订阅者方法,另外还有一个是必须的,就是通知各个订阅者消息的方法 notifyObservers()。那 Observable 接口代码以下所示。this

interface Observable {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String message);
}

实现 Observer 接口的对象说明是能够去订阅观察的,也就是说能够接收被订阅的对象发出来的消息,那就须要一个接收消息的方法 update()。代码以下所示。设计

interface Observer {
    void update(String name, String message);
}

为了让你们不混淆,先把观察者和被观察者分离开,其实在这个例子中,观察者和被观察者是同一个对象 User 的。这里就分开,分红 UserFriend,后面会给出正确的代码,稍安勿躁哈。这里 User 做为被观察者,实现了 Observable 接口,而 Friend 做为观察者,实现了 Observer 接口。代码以下。code

class User implements Observable {

    private List<Observer> friends;
    private String name;

    public User(String name) {
        this.name = name;
        this.friends = new LinkedList<>();
    }

    public void sendMessage(String message) {
        this.notifyObservers(message);
    }

    @Override
    public void addObserver(Observer observer) {
        this.friends.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        this.friends.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        this.friends.forEach(friend -> {
            friend.update(this.name, message);
        });
    }
}

class Friend implements Observer {

    private String name;

    public Friend(String name) {
        this.name = name;
    }
    @Override
    public void update(String name, String message) {
        System.out.println("【" + this.name + "】看到【" + name + "】发的朋友圈:" + message);
    }
}

public class ObserverTest {

    public static void main(String[] args) {
        User xiaoMing = new User("小明");
        Friend xiaoHong = new Friend("小红");
        Friend xiaoDong = new Friend("小东");
        xiaoMing.addObserver(xiaoHong);
        xiaoMing.addObserver(xiaoDong);
        xiaoMing.sendMessage("今天真开心");
        // 小红和小明闹别扭了,小红取消订阅小明的朋友圈
        xiaoMing.removeObserver(xiaoHong);
        xiaoMing.sendMessage("但愿明天也像今天同样开心");
    }

}

打印结果:
【小红】看到【小明】发的朋友圈:今天真开心
【小东】看到【小明】发的朋友圈:今天真开心
【小东】看到【小明】发的朋友圈:但愿明天也像今天同样开心

看到代码执行结果,小红和小东都订阅了小明的朋友圈,小明发了朋友圈:今天真开心。他们俩都收到了,由于小红和小明闹别扭,小红取消订阅小明的朋友圈,因此小明后来发的朋友圈,小红没收到。server

上面代码实际上是不对的,不该该用 UserFriend 2 个类来定义。若是小明订阅小红和小东的朋友圈呢?这样实现比较麻烦,主要是为了分清 观察者被观察者 这 2 个概念,经过上面的例子应该分清楚了 2 个概念了,那就能够来看正确的代码,小明、小红、小东他们其实都是观察者和被观察者,因此咱们用 User2 来定义他们就能够,User2 实现了 ObservableObserver 接口。代码以下。对象

class User2 implements Observable, Observer {

    private List<Observer> friends;
    private String name;

    public User2(String name) {
        this.name = name;
        this.friends = new LinkedList<>();
    }

    @Override
    public void addObserver(Observer observer) {
        this.friends.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        this.friends.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        this.friends.forEach(friend -> {
            friend.update(this.name, message);
        });
    }

    @Override
    public void update(String name, String message) {
        System.out.println("【" + this.name + "】看到【" + name + "】发的朋友圈:" + message);
    }

    public void sendMessage(String message) {
        this.notifyObservers(message);
    }
}

public class ObserverTest {

    public static void main(String[] args) {
        User2 xiaoMing2 = new User2("小明");
        User2 xiaoHong2 = new User2("小红");
        User2 xiaoDong2 = new User2("小东");
        xiaoMing2.addObserver(xiaoHong2);
        xiaoMing2.addObserver(xiaoDong2);
        xiaoMing2.sendMessage("今天真开心");
        xiaoMing2.removeObserver(xiaoHong2);
        xiaoMing2.sendMessage("但愿明天也像今天同样开心");

        xiaoHong2.addObserver(xiaoMing2);
        xiaoHong2.addObserver(xiaoDong2);
        xiaoHong2.sendMessage("今天和小明吵架了,屏蔽他的朋友圈");

        xiaoDong2.addObserver(xiaoMing2);
        xiaoDong2.addObserver(xiaoHong2);
        xiaoDong2.sendMessage("小明和小红吵架了,夹在中间好尴尬");
    }

}

打印结果:
【小红】看到【小明】发的朋友圈:今天真开心
【小东】看到【小明】发的朋友圈:今天真开心
【小东】看到【小明】发的朋友圈:但愿明天也像今天同样开心
【小明】看到【小红】发的朋友圈:今天和小明吵架了,屏蔽他的朋友圈
【小东】看到【小红】发的朋友圈:今天和小明吵架了,屏蔽他的朋友圈
【小明】看到【小东】发的朋友圈:小明和小红吵架了,夹在中间好尴尬
【小红】看到【小东】发的朋友圈:小明和小红吵架了,夹在中间好尴尬

从代码中,咱们看到小明、小红、小东 3 我的互相订阅朋友圈,固然中途小红屏蔽了小明的朋友圈。这就是 观察者被观察者 恰好是同一个对象的实现。

总结

观察者模式 是一个比较特殊的设计模式,它定义了触发机制,观察者只要订阅了被观察者,就能够第一时间获得被观察者传递的信息。在工做中,使用观察者模式的场景也比较多,好比消息队列消费,Android 开发中的事件触发机制等等。好,观察者模式就到这。

推荐阅读:

行为型模式:迭代器模式

行为型模式:策略模式

行为型模式:责任链模式

设计模式系列文章持续更新中,欢迎关注公众号 LieBrother,一块儿交流学习。

相关文章
相关标签/搜索