js观察者模式浅谈

定义

  • 观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己
  • 观察者模式是软件设计模式的一种常见的设计模式,又称发布订阅模式。在这种模式中,并不是单纯的一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的特定活动并在其状态发生改变后获得通知,然后执行相应的操作。订阅者也称为观察者,而被观察的对象则被称为发布者或主题。当一个事件发生,发布者将会向所有订阅此事件的对象以事件对象的形式传递消息。
使用观察者模式的好处
  1. 支持简单的广播通信,自动通知所有已经订阅过的对象。
  2. 页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
  3. 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。
介绍
  1. 发布 & 订阅
  2. 一对多

实现

在这里插入图片描述

 <script>
        //发布者,接受状态变化,触发每个观察者
    class Subject {
        constructor() {
            this.state = 0 //记录信息的状态
            this.observers = []//用来储存观察者
        }
        getState() { //获取状态信息
            return this.state
        }
        setState(state) { //发布者状态信息的改变
            this.state = state
            this.notifyAllObservers()
        }
        attach(observer) { //添加每一个观察者
            this.observers.push(observer)
        }
        notifyAllObservers() {   //触发所有观察者执行updata()
            this.observers.forEach(observer => {
                observer.update()
            })
        }
    }
        // 观察者(订阅者),等待被触发
        class Observer {
        constructor(name, subject) { 
            this.name = name
            this.subject = subject
            this.subject.attach(this) //把每一个观察者对象添加到发布者的观察者数组队列中
        }
        update() {
            console.log(`${this.name} update, state: ${this.subject.getState()}`)
        }
        }

// 测试代码
let s = new Subject();
let ob1 = new Observer('小明', s);
let ob2 = new Observer('小红', s);
let ob3 = new Observer('小花', s);

console.log(s);
s.setState("明天暴雨")
s.setState("后天初雪")
s.setState("大后天晴朗")
    </script>

在这里插入图片描述

    <script>
        //发布者
        function Subject(){
            this.list = [];
        }
        Subject.prototype = {
            constructor : Subject,
               // 订阅
            on : function( obs ){
                this.list.push( obs );
            },
               //发布
            emmit : function(msg){ 
                this.list.forEach( function( obs ){//obs其实是一个观察者的对象
                    obs.strategy( msg );
                })
            },
                //删除
            delete : function( obs ){
                this.list.splice( this.list.indexOf(obs) , 1 )
            }   
        }
        // 订阅者;
        function Obs( name ){
            this.name = name;
        }
        Obs.prototype.strategy = function( msg ){//msg这个形参表示的是观察者里面的方法名
            typeof this[msg] === "function" ? this[msg]() : "";//因为这里面有一个判断当this.函数名是一个方法则去执行这个方法
        }
        Obs.prototype.rain = function(){
            console.log("明天下雨");
        }
        Obs.prototype.sunny = function(){
            console.log("明天下雪");
        }

        var sub = new Subject();
        sub.on( new Obs("小明") );
        sub.on( new Obs("小红") );
        sub.on( new Obs("小花") );
        console.log(sub)
        sub.emmit("rain");
    </script>

在这里插入图片描述

实战

 function Observer(){
            this.list = {};
        }
        Observer.prototype = {
            constructor : Observer,
            on : function( sub , type ){
                type = type || "default";
                // 判定对应类别之中是否为数组;
                if(this.list[type] && this.list[type] instanceof Array){
                    // 如果是数组直接放入;
                    this.list[type].push(sub);
                }else{
                    // 如果不是数组建立数组结构;
                    this.list[type] = [sub];
                }
            },
            emmit : function(msg , type){
                type = type || "default";
                if(this.list[type] instanceof Array){
                    this.list[type].forEach( function( sub ){
                        sub.strategy( msg );
                    })
                }
            },
            delete : function( sub , type ){
                this.list[type].splice( this.list[type].indexOf(sub) , 1 )
            }   
        }
        //订阅者;
        function Sub( name ){
            this.name = name;
        }
        Sub.prototype.strategy = function( msg ){
            typeof this[msg] === "function" ? this[msg]() : "";
        }
        Sub.prototype.happy = function(){
            console.log("我好开心啊");
        }
        Sub.prototype.unhappy = function(){
            console.log("我好难过啊");
        }
        // 黑粉 ;
        function Sub2( name ){
            this.name = name;
        }
        Sub2.prototype.strategy = function( msg ){
            typeof this[msg] === "function" ? this[msg]() : "";
        }
        Sub2.prototype.happy = function(){
            console.log("我好难过");
        }
        Sub2.prototype.unhappy = function(){
            console.log("我号开心");
        }
        var obs = new Observer();
        obs.on( new Sub("订阅者1") );
        obs.on( new Sub("订阅者2") );
        obs.on( new Sub("订阅者3") );
        obs.on( new Sub("订阅者4") );
        obs.on( new Sub2("订阅者5") , "heifen" );
        obs.on( new Sub2("订阅者6") , "heifen" );
        // console.log(obs)
        obs.emmit("happy" );
        obs.emmit("happy","heifen" );

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值