观察者和代理模式

6次阅读

共计 2326 个字符,预计需要花费 6 分钟才能阅读完成。

设计模式

设计模式,不是工具,是软件开发的哲学。它指导你如何去设计一个优秀的架构、编写一段健壮的代码、解决一个复杂的问题。

定个小目标

我是程序员,我想写出更加优雅的代码

观察者模式????

定义

定义对象间一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有依赖它的观察者对象,使得它们能够自动更新自己

角色组成

  1. Subject 抽象主题目标:维护一些列的观察者,提供添加或删除观察者的接口
  2. Observer 抽象观察者:为目标状态发生改变时需要通知的对象提供一个接口
  3. ConcreteSubject 具体主题目标:发生变化时通知观察者
  4. ConcreteObserver 具体观察者:实现具体的更新方法

优缺点

  • 优点:观察者和被观察之间是抽象耦合,容易扩展
  • 缺点:(Java 中消息通知默认是顺序执行,而 Javascript 异步实现)多级触发效率问题

使用场景

  • 关联行为场景
  • 事件多级触发场景
  • 跨系统的消息交换场景

注意事项

双重身份观察者,建议一个观察者模式实现中,最多只有一个对象既是观察者也是被观察者,避免形成复杂的广播链,降低系统可维护性。

改造

  • 观察者和被观察者之间的消息沟通:观察者的 update 方法接收两个参数,一个是被观察者,一个是 DTO 数据传输对象
  • 观察者响应方式:一个观察者多个被观察者,采用多线程技术或缓存技术完成响应
  • 被观察者尽量自己做主:不是所有的改变都需要通知观察者,先判断一下

观察者模式 vs 发布订阅模式

vue2.x 中的应用

  • 被观察者:data / prop
  • 观察者:watcher
  • 调度中心:dep

https://ustbhuangyi.github.io…

vue2.x 响应式原理
  • 核心:ES5 的 Object.defineProperty(obj, prop, descriptor)(不兼容 IE8 及以下浏览器)

    get 是给属性提供一个 getter 方法,每次访问该属性会触发 getter 方法,setter 提供属性修改时触发的 setter 方法

    (采用 数据劫持结合发布 - 订阅者模式 ,通过 Object.defineProperty() 劫持各个属性的 getter 和 setter,在数据变动时发布消息给订阅者,触发相应的监听回调)

  • 初始化:Vue 的初始化阶段,会对 data/props 进行初始化操作,遍历 data/props,(observe/ defineReactive 方法)内部调用 Object.defineProperty 给每个属性加上 getter、setter,getter 用于依赖收集,setter 用于派发更新;
  • 依赖收集:核心是一个 Dep,Dep 是连接数据和对应观察者的桥梁,每个对象的 getter 都持有一个 dep 实例,(访问数据)触发 getter 时,会调用 dep.depend 方法,让当前 watcher 订阅数据,为后面的数据变化通知做准备(每次添加完新的订阅,会移除旧的订阅)
  • 派发更新:当修改响应数据时,会触发 setter,调用 dep.notify()方法,通知所有订阅者,也就是 watcher 触发更新

代理模式

定义

为其他对象提供一种代理以控制对这个对象的访问。

角色组成

  1. Subject 抽象主题
  2. RealSubject 具体主题:被代理角色,业务逻辑的具体执行者
  3. Proxy 代理:代理类

优缺点

  • 优点:职责清晰;高扩展性;智能化
  • 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢;实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

使用场景

  • 远程代理:为一个对象在不同的地址空间提供局部代表,隐藏一个对象存在与不同地址空间的事实
  • 虚拟代理:根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象
  • 安全代理:用来控制真实对象访问时的权限
  • 智能引用:调用真实对象时,代理处理一些额外的事。

扩展

  • 普通代理:只能访问代理角色,不能访问真实角色(调用者只知道代理,不知道真实角色)
  • 强制代理:必须通过真实角色找到代理角色
  • 动态代理:AOP 面向切面编程

通晓 23 种设计模式,你可以站在一个更高的层次去赏析程挂·序代码、软件设计、架构,完成代码工人到架构师的蜕变。真正的理解设计模式,需要工作经验的积累。

参考资料

《设计模式之蝉》

Z 同学学习总结:

观察者模式:

观察者模式适用场景,一个功能的变化会影响到其他模块产生对应自己的变化的操作,这种场景就适用用来适用观察者模式。如: 直播送礼物,送礼物以后,用户的等级、经验,与直播的亲密度、主播的榜单、用户在主播房间内的榜单排行,通知弹幕下发礼物特效等等。也就是送礼物操作以后会影响到其他模块进行操作进行变化,这种场景就比较适合用观察者模式。

观察者模式里面并没有实现观察者和订阅者的解耦,同时我们也可以引用外部组件实现观察订阅模式,如引入消息队列,如 kafka, 引入外部组件的坏处是,当引入的外部组件每多一个,系统出问题的时候,排查问题的复杂性就会增加。

代理模式:
我当下的理解是,A 想向 C 通信,这个过程中,A 又有点害羞,不想直接和 C 通信,这个时候想通过 B 给 C 通信,那么 A 和 B 都有类似的实现,然后 A 传给 B,调用 B 的方法和 C 通信。

设计模式学习和使用:

讲设计模式的时候大家觉得都不是很好讲,其中一方面是我们日常使用的少,没有体会到使用设计模式的优点和价值,另一方面也是我们并没有体会到设计模式的精髓,所以后者需要我们在后面的学习和使用中加深影响,更加深刻的理解设计模式。

我觉得设计模式和我们平常学习其他东西都要经历这几个阶段,知道有这个东西,然后去使用,发现用的不是很好,然后回过头再去仔细的看为什么这样使用,然后深刻理解以后,更好的应用在我们的代码和系统当中。

知道 – 使用 – 理解为什么 – 更好的应用

正文完
 0