观察者模式

定义

多个对象之间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并执行相应的行为;有点消息队列的意思

架构

抽象主题:提供一个用于保存订阅者对象的聚集类和增加、删除订阅者对象的方法,以及通知所有订阅者的抽象方法;
具体主题:实现抽象主题中的通知方法,当具体主题的内部状态发生变化的时候通知所有注册过的观察者对象;
抽象订阅者:可以是抽象类也可以是接口,包含一个更新自己的抽象方法,当接到具体主题的更改通知时被调用;
具体订阅者:实现抽象订阅者中的抽象方法,以便在得到目标的更改通知时更新自己的状态。

应用场景

1、对象间存在一对多的关系,一个对象的状态发生改变会影响其他对象;
2、当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,可将这二者封装在独立的对象中以使它们可以各独自地改变和复用;
3、实现类似广播地功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收广播;
4、多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种订阅者类型)通知;

代码

观察者模式
Topic(抽象主题)

/**
 *
 * Description:
 *          抽象目标
 *          (所有公众号的父类)
 * @author: mushi
 * @Date: 2021/2/22 10:46
 */
public abstract class Topic {

    private List<Fans> fansList = new ArrayList();

    //添加观察者(粉丝)
    public void addFans(Fans fans){
        fansList.add(fans);
    }

    //删除观察者(粉丝)
    public void removeFans(Fans fans){
        fansList.remove(fans);
    }

    public List<Fans> getFansList() {
        return fansList;
    }

    public void setFansList(List<Fans> fansList) {
        this.fansList = fansList;
    }

    //通知观察者(群发消息)
    public abstract void sendMsgToAllFans(String msg);

    //接收观察者发送的消息(接收来自粉丝的消息)
    public abstract void receiver(String fansName,String msg);

}

TopicA(具体主题)

/**
 *
 * Description:
 *          具体目标
 *          (具体公众号)
 * @author: mushi
 * @Date: 2021/2/22 10:52
 */
public class TopicA extends Topic{

    @Override
    public void sendMsgToAllFans(String msg) {
        //发消息给所有粉丝
        List<Fans> fansList = super.getFansList();
        for (Fans fans : fansList){
            fans.receiver(msg);
        }
    }

    @Override
    public void receiver(String fansName, String msg) {
        //接收来自粉丝的消息
        System.out.println("公众号=收到粉丝"+fansName+"发来的:"+msg);
    }
}

Fans(抽象订阅者)

/**
 *
 * Description:
 *          抽象订阅者
 * @author: mushi
 * @Date: 2021/2/22 10:51
 */
public interface Fans {

    /**接收消息*/
    void receiver(String msg);

    /**发送消息*/
    void send(String msg);

}

FansA(具体订阅者A)

/**
 *
 * Description:
 *
 * @author: mushi
 * @Date: 2021/2/22 10:56
 */
public class FansA implements Fans {

    private String name;

    @Override
    public void receiver(String msg) {
        System.out.println("粉丝="+this.name+"=收到消息:"+msg);
    }

    @Override
    public void send(String msg) {
        TopicA topicA = new TopicA();
        topicA.receiver(name,msg);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

FansB(具体订阅者B)

/**
 *
 * Description:
 *
 * @author: mushi
 * @Date: 2021/2/22 10:58
 */
public class FansB implements Fans {

    private String name;

    @Override
    public void receiver(String msg) {
        System.out.println("粉丝="+this.name+"=收到消息:"+msg);
    }

    @Override
    public void send(String msg) {
        Topic topicA = new TopicA();
        topicA.receiver(name,msg);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Test

/**
 *
 * Description:
 *          观察者模式
 * @author: mushi
 * @Date: 2021/2/22 10:58
 */
public class Test {

    public static void main(String[] args) {

        //创建公众号
        Topic topicA = new TopicA();

        //创建粉丝
        Fans fansA = new FansA();
        ((FansA) fansA).setName("洛夫斯基");
        Fans fansB = new FansB();
        ((FansB) fansB).setName("俄罗斯套娃");

        //粉丝关注公众号
        topicA.addFans(fansA);
        topicA.addFans(fansB);

        //公众号群发消息
        topicA.sendMsgToAllFans("芜湖起飞");

        //粉丝给公众号发消息
        fansA.send("我是洛夫斯基");
        fansB.send("我是套娃");
    }

}

总结

以公众号为例,
多个用户关注公众号,公众号知道有哪些人关注着自己;
当公众号发一条消息的时候,所有关注这个公众号的人都可以接收到;

这种类似广播的机制,在实际生活当中有着很多例子,消息队列的行为模式也有点类似(消息发布者、消息处理者)但具体的实现方式肯定没有这么简单,只是说行为上有点类似;

代码的逻辑就是,一个类管理着一组对象,要想让每个对象都接收到消息,遍历存放对象的数组,令数组里的每个对象都执行接收消息的方法。

上一篇:tp6.x关联统计添加查询条件


下一篇:099-Spark-源码-SparkSubmit