美文网首页
观察者模式:将对象的状态监听器抽象

观察者模式:将对象的状态监听器抽象

作者: HWilliamgo | 来源:发表于2019-03-29 15:26 被阅读0次

    回调、监听器、观察者模式。这三个名词描述的都是同一件事物:

    一个有状态的对象,将自身的状态发布出去,通知到那些订阅了该对象的状态的观察者(们)。

    举例子:微信用户关注(或者说订阅)一个公众号,当公众号作者发布一篇推文时,所有订阅了这个公众号的用户都能收到推送。

    被观察者,都是有状态的对象,将自己的某个状态发布给订阅了他的对象们。

    代码举例:

    class Author {
        private var onPublishEssayListener: ((id: String) -> Unit)? = null
        private var onUpdateEssayListener: ((id: String) -> Unit)? = null
        private var onDeleteEssayListener: ((id: String) -> Unit)? = null
    
        fun publishEssay() {
            //...
    
            //由Author自己维护何时发布回调
            onPublishEssayListener?.invoke("123")
    
            //...
        }
    
        fun deleteEssay() {
            //..
    
            //由Author自己维护何时发布回调
            onDeleteEssayListener?.invoke("123")
    
            //..
        }
    
        fun updateEssay() {
            //..
    
            //由Author自己维护何时发布回调
            onUpdateEssayListener?.invoke("123")
    
            //..
        }
        
        fun observePublish(onPublishEssayListener: (id: String) -> Unit) {
            this.onPublishEssayListener = onPublishEssayListener
        }
    
        fun observeUpdate(onUpdateEssayListener: (id: String) -> Unit) {
            this.onUpdateEssayListener = onUpdateEssayListener
        }
    
        fun observeDelete(onDeleteEssayListener: (id: String) -> Unit) {
            this.onDeleteEssayListener = onDeleteEssayListener
        }
    }
    
    fun main(args: Array<String>) {
    
        val author = Author()
    
        author.observePublish { id ->
            log("发布文章,id=$id")
        }
    
        author.observeUpdate { id ->
            log("更新文章,id=$id")
        }
        author.observeDelete { id ->
            log("删除文章。id=$id")
        }
        author.publishEssay()
        author.updateEssay()
        author.deleteEssay()
    }
    

    打印:

    发布文章,id=123
    更新文章,id=123
    删除文章。id=123
    

    上述代码由Author类直接引用了回调(用了Kotlin中的函数类型,省去了定义多个接口),在Authoer类的内部来直接根据当前的逻辑,将注册过来的观察者给发布出去。这里可以将这些观察者(或者说回调对象)抽象出来,做成一个父类,让Author继承。

    因为观察者观察的都是文章的状态,因此这个类叫做EssayStateRegistry

    abstract class EssayStateRegistry {
        private var onPublishEssayListener: ((id: String) -> Unit)? = null
        private var onUpdateEssayListener: ((id: String) -> Unit)? = null
        private var onDeleteEssayListener: ((id: String) -> Unit)? = null
    
        //-------------状态的通知------------------
        protected fun notifyPublish(id: String) {
            onPublishEssayListener?.invoke(id)
        }
    
        protected fun notifyUpdate(id: String) {
            onUpdateEssayListener?.invoke(id)
        }
    
        protected fun notifyDelete(id: String) {
            onDeleteEssayListener?.invoke(id)
        }
        
        //------------状态的订阅--------------------
        fun observePublish(onPublishEssayListener: (id: String) -> Unit) {
            this.onPublishEssayListener = onPublishEssayListener
        }
    
        fun observeUpdate(onUpdateEssayListener: (id: String) -> Unit) {
            this.onUpdateEssayListener = onUpdateEssayListener
        }
    
        fun observeDelete(onDeleteEssayListener: (id: String) -> Unit) {
            this.onDeleteEssayListener = onDeleteEssayListener
        }
    }
    

    此时的Authoer便干净了许多

    //继承了EssayStateRegistry
    class Author : EssayStateRegistry() {
        fun publishEssay() {
            //...
    
            //由Author自己维护何时发布回调
            notifyPublish("123")
            //...
        }
    
        fun deleteEssay() {
            //..
    
            //由Author自己维护何时发布回调
            notifyDelete("123")
            //..
        }
    
        fun updateEssay() {
            //..
    
            //由Author自己维护何时发布回调
            notifyUpdate("123")
            //..
        }
    }
    

    主程序代码不需要改变。

    fun main(args: Array<String>) {
    
        val author = Author()
    
        author.observePublish { id ->
            log("发布文章,id=$id")
        }
    
        author.observeUpdate { id ->
            log("更新文章,id=$id")
        }
        author.observeDelete { id ->
            log("删除文章。id=$id")
        }
        author.publishEssay()
        author.updateEssay()
        author.deleteEssay()
    }
    

    打印

    发布文章,id=123
    更新文章,id=123
    删除文章。id=123
    

    特点:

    1. 将有状态的对象Author与他的观察、订阅逻辑分离。他自己不再直接维护他的状态。他的状态的订阅和发布的处理细节抽象给父类。他自己只需要继承父类就可以获得转发自己状态的能力。

    优点:

    1. 逻辑分离,简化有状态的对象Author的代码,让其专注主要的逻辑。
    2. 抽象出来的父类EssayStateRegistry可以拓展,其他对象只需要继承父类,就可以瞬间拥有所有父类的状态和维护状态的能力。
    3. 当未来可能有更多的状态需要Author类拓展,那么可以再抽象出一个父类XXXStateRegistry来让Author继承,此时Author的代码将依然保持简洁。

    缺点:

    1. 继承就是耦合,抽象父类的任何的改动,都将影响所有继承了父类的子类。

    图:

    相关文章

      网友评论

          本文标题:观察者模式:将对象的状态监听器抽象

          本文链接:https://www.haomeiwen.com/subject/ofglbqtx.html