国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從發(fā)布-訂閱模式到Vue響應(yīng)系統(tǒng)

zacklee / 1053人閱讀

摘要:典型實(shí)現(xiàn)例子售樓處的例子一步步實(shí)現(xiàn)發(fā)布訂閱模式首先指定好誰充當(dāng)發(fā)布者售樓處然后給發(fā)布者添加一個(gè)緩存列表,用語存放回調(diào)函數(shù),以便通知訂閱者售樓處花名冊。最后發(fā)布消息的時(shí)候,發(fā)布者會(huì)遍歷這個(gè)緩存列表,依次觸發(fā)里面存放的訂閱者的回調(diào)函數(shù)。

概念

發(fā)布-訂閱模式又稱為觀察者模式,它定義的是一種一對多的依賴關(guān)系,當(dāng)一個(gè)狀態(tài)發(fā)生改變的時(shí)候,所有以來這個(gè)狀態(tài)的對象都會(huì)得到通知。

生活中的發(fā)布-訂閱模式

上面事發(fā)布-訂閱模式的一個(gè)比較正式的解釋,可能這個(gè)解釋不大好理解。所以我們通過實(shí)際生活中的例子來理解。

比如看中了一套房子,等到去了售樓處的說以后才被告知房子已經(jīng)售罄了。但是售樓小姐告知,將來會(huì)有尾盤推出。具體什么時(shí)候推出,目前沒人知道。

但是買家又不想頻繁的跑,于是就把自己的電話號碼登記在售樓處,在登記的花名冊上有很多類似的買家。售樓小姐答應(yīng)買家,新的房源一出來就一一通知買家。

所以上面就是一個(gè)發(fā)布訂閱模式的簡單例子。購房者(訂閱者)訂閱房源信息,售樓處(發(fā)布者)發(fā)布新房源消息給購房者(訂閱者),購房者(訂閱者)接收到消息后作出相應(yīng)的反應(yīng)。

適用性

發(fā)布訂閱模式可以廣泛的應(yīng)用于異步編程中。

發(fā)布訂閱模式可以取代對象之間的硬編碼通知機(jī)制。

典型實(shí)現(xiàn)例子
1、售樓處的例子

一步步實(shí)現(xiàn)發(fā)布訂閱模式:

首先指定好誰充當(dāng)發(fā)布者(售樓處)

然后給發(fā)布者添加一個(gè)緩存列表,用語存放回調(diào)函數(shù),以便通知訂閱者(售樓處花名冊)。

最后發(fā)布消息的時(shí)候,發(fā)布者會(huì)遍歷這個(gè)緩存列表,依次觸發(fā)里面存放的訂閱者的回調(diào)函數(shù)。

let salesOffices = {} // 售樓處
salesOffices.books = [] // 緩存列表,存放訂閱者的回調(diào)函數(shù)。
// 增加訂閱者
salesOffices.listen = function(fn) {
  this.books.push(fn) // 訂閱的消息添加近緩存列表里面
}
salesOffices.trigger = function() {
  // 發(fā)布消息
  for (let i = 0, fn; (fn = salesOffices.books[i++]); ) {
    fn.apply(this, arguments) // arguments 是發(fā)布消息的時(shí)候帶上的參數(shù)
  }
}

salesOffices.listen(function(price, squareMeter) {
  // 購買者a
  console.log(`價(jià)格是:${price}`)
  console.log(`面積大小:${squareMeter}`)
})
salesOffices.listen(function(price, squareMeter) {
  // 購買者b
  console.log(`價(jià)格是:${price}`)
  console.log(`面積大小:${squareMeter}`)
})

salesOffices.trigger(2000000, 88)
salesOffices.trigger(3000000, 128)

上面實(shí)現(xiàn)了一個(gè)最簡單的發(fā)布訂閱模式。肯定還有很多問題的,例如訂閱者只訂閱了某一個(gè)消息,但是上面會(huì)把所有消息發(fā)給每一個(gè)訂閱者。所以還得通過其他的方式讓訂閱者只訂閱自己感興趣的消息。

2、vue 對發(fā)布訂閱模式的使用

我們都知道 Vue 有個(gè)最顯著的特性,便是侵入性不是很強(qiáng)的響應(yīng)式系統(tǒng)。這個(gè)特性就是對發(fā)布訂閱模式非常好的應(yīng)用。我們接下來就來看看這個(gè)特性是怎么應(yīng)用的。

vue 的數(shù)據(jù)初始化:

var v = new Vue({
  data() {
    return {
      a: "hello"
    }
  }
})

這個(gè)初始化的代碼的背后包含著發(fā)布訂閱模式的思想,接下來看看官網(wǎng)的一個(gè)圖

接下來就是網(wǎng)友的一個(gè)圖:@xuqiang521

1. 數(shù)據(jù)劫持

從上圖可以看到,數(shù)據(jù)劫持的核心方法就是使用Object.defineProperty把屬性轉(zhuǎn)化成getter/setter。(因?yàn)檫@個(gè)是 ES5 中的方法,所以這也是 Vue 不支持 ie8 及以下瀏覽器的原因之一。)在數(shù)據(jù)傳遞變更的時(shí)候,會(huì)進(jìn)入到我們封裝的DepWatcher中進(jìn)行處理。

1.1 遍歷劫持

數(shù)據(jù)不緊緊是基本類型的數(shù)據(jù),也有可能是對象或者數(shù)組。基本類型的數(shù)據(jù)和對象的處理起來比較簡單。

walk(obj) {
  const keys = Object.keys(obj)
  for (let i = 0; i < keys.length; ++i) {
    defineReactive(obj, keys[i], obj[keys[i]])
  }
}

核心的劫持相關(guān)函數(shù)以及屬性的訂閱和發(fā)布

/**
 * Define a reactive property on an Object.
 */
export function defineReactive(
  obj: Object,
  key: string,
  val: any,
  customSetter?: Function
) {
  /*在閉包中定義一個(gè)dep對象*/
  const dep = new Dep()

  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  /*如果之前該對象已經(jīng)預(yù)設(shè)了getter以及setter函數(shù)則將其取出來,新定義的getter/setter中會(huì)將其執(zhí)行,保證不會(huì)覆蓋之前已經(jīng)定義的getter/setter。*/
  // cater for pre-defined getter/setters
  const getter = property && property.get
  const setter = property && property.set

  /*對象的子對象遞歸進(jìn)行observe并返回子節(jié)點(diǎn)的Observer對象*/
  let childOb = observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      /*如果原本對象擁有g(shù)etter方法則執(zhí)行*/
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        /*進(jìn)行依賴收集*/
        dep.depend()
        if (childOb) {
          /*子對象進(jìn)行依賴收集,其實(shí)就是將同一個(gè)watcher觀察者實(shí)例放進(jìn)了兩個(gè)depend中,一個(gè)是正在本身閉包中的depend,另一個(gè)是子元素的depend*/
          childOb.dep.depend()
        }
        if (Array.isArray(value)) {
          /*是數(shù)組則需要對每一個(gè)成員都進(jìn)行依賴收集,如果數(shù)組的成員還是數(shù)組,則遞歸。*/
          dependArray(value)
        }
      }
      return value
    },
    set: function reactiveSetter(newVal) {
      /*通過getter方法獲取當(dāng)前值,與新值進(jìn)行比較,一致則不需要執(zhí)行下面的操作*/
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== "production" && customSetter) {
        customSetter()
      }
      if (setter) {
        /*如果原本對象擁有setter方法則執(zhí)行setter*/
        setter.call(obj, newVal)
      } else {
        val = newVal
      }

      /*新的值需要重新進(jìn)行observe,保證數(shù)據(jù)響應(yīng)式*/
      childOb = observe(newVal)

      /*dep對象通知所有的觀察者*/
      dep.notify()
    }
  })
}

最開始在初始化的時(shí)候是對 data 里面的數(shù)據(jù)就開始劫持監(jiān)聽了。初始化的時(shí)候就調(diào)用了observe方法

/**
 * Attempt to create an observer instance for a value,
 * returns the new observer if successfully observed,
 * or the existing observer if the value already has one.
 */
/*
 嘗試創(chuàng)建一個(gè)Observer實(shí)例(__ob__),如果成功創(chuàng)建Observer實(shí)例則返回新的Observer實(shí)例,如果已有Observer實(shí)例則返回現(xiàn)有的Observer實(shí)例。
 */
export function observe(value: any, asRootData: ?boolean): Observer | void {
  /*判斷是否是一個(gè)對象*/
  if (!isObject(value)) {
    return
  }
  let ob: Observer | void

  /*這里用__ob__這個(gè)屬性來判斷是否已經(jīng)有Observer實(shí)例,如果沒有Observer實(shí)例則會(huì)新建一個(gè)Observer實(shí)例并賦值給__ob__這個(gè)屬性,如果已有Observer實(shí)例則直接返回該Observer實(shí)例*/
  if (hasOwn(value, "__ob__") && value.__ob__ instanceof Observer) {
    ob = value.__ob__
  } else if (
    /*這里的判斷是為了確保value是單純的對象,而不是函數(shù)或者是Regexp等情況。*/
    observerState.shouldConvert &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
    ob = new Observer(value)
  }
  if (asRootData && ob) {
    /*如果是根數(shù)據(jù)則計(jì)數(shù),后面Observer中的observe的asRootData非true*/
    ob.vmCount++
  }
  return ob
}
1.2 返回值

上面的數(shù)據(jù)observe之后返回的就是一個(gè) Observer 的實(shí)例

ob = new Observer(value)

return ob
2."中轉(zhuǎn)站"

在第一步數(shù)據(jù)劫持的時(shí)候,數(shù)據(jù)的獲取或者修改的時(shí)候,都會(huì)做出對應(yīng)的操作。這些操作的目的很簡單,就是“通知”到“中轉(zhuǎn)站”。這個(gè)“中轉(zhuǎn)站”主要就是對數(shù)據(jù)的變更起通知作用以及存放依賴這些數(shù)據(jù)的“地方”。

這個(gè)"中轉(zhuǎn)站"就是由"Dep"和“Watcher” 類構(gòu)成的。每個(gè)被劫持的數(shù)據(jù)都會(huì)產(chǎn)生一個(gè)這樣的“中轉(zhuǎn)站”

2.1 Dep

Dep,全名 Dependency,從名字我們也能大概看出 Dep 類是用來做依賴收集的,但是也有通知對應(yīng)的訂閱者的作用 ,讓它執(zhí)行自己的操作,具體怎么收集呢?

/**
 * A dep is an observable that can have multiple
 * directives subscribing to it.
 */
export default class Dep {
  static target: ?Watcher
  id: number
  subs: Array

  constructor() {
    this.id = uid++
    this.subs = []
  }

  /*添加一個(gè)觀察者對象*/
  addSub(sub: Watcher) {
    this.subs.push(sub)
  }

  /*移除一個(gè)觀察者對象*/
  removeSub(sub: Watcher) {
    remove(this.subs, sub)
  }

  /*依賴收集,當(dāng)存在Dep.target的時(shí)候添加觀察者對象*/
  depend() {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }

  /*通知所有訂閱者*/
  notify() {
    // stabilize the subscriber list first
    const subs = this.subs.slice()
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }
}

// the current target watcher being evaluated.
// this is globally unique because there could be only one
// watcher being evaluated at any time.
Dep.target = null
/*依賴收集完需要將Dep.target設(shè)為null,防止后面重復(fù)添加依賴。*/
const targetStack = []
export function pushTarget(_target: Watcher) {
  if (Dep.target) targetStack.push(Dep.target)
  // 改變目標(biāo)指向
  Dep.target = _target
}

export function popTarget() {
  // 刪除當(dāng)前目標(biāo),重算指向
  Dep.target = targetStack.pop()
}

代碼很簡短,但它做的事情卻很重要

定義 subs 數(shù)組,用來收集訂閱者 Watcher

當(dāng)劫持到數(shù)據(jù)變更的時(shí)候,通知訂閱者 Watcher 進(jìn)行 update 操作

2.2 Watcher

Watcher 就是訂閱者(觀察者)。 主要的作用就是就是訂閱 Dep(每個(gè)屬性都會(huì)有一個(gè) dep),當(dāng) Dep 發(fā)出消息傳遞(notify)的時(shí)候,所以訂閱著 Dep 的 Watchers 會(huì)進(jìn)行自己的 update 操作。

export default class Watcher {
  vm: Component
  expression: string
  cb: Function
  id: number
  deep: boolean
  user: boolean
  lazy: boolean
  sync: boolean
  dirty: boolean
  active: boolean
  deps: Array
  newDeps: Array
  depIds: ISet
  newDepIds: ISet
  getter: Function
  value: any

  constructor(
    vm: Component,
    expOrFn: string | Function,
    cb: Function,
    options?: Object
  ) {
    this.vm = vm
    /*_watchers存放訂閱者實(shí)例*/
    vm._watchers.push(this)
    // options
    if (options) {
      this.deep = !!options.deep
      this.user = !!options.user
      this.lazy = !!options.lazy
      this.sync = !!options.sync
    } else {
      this.deep = this.user = this.lazy = this.sync = false
    }
    this.cb = cb
    this.id = ++uid // uid for batching
    this.active = true
    this.dirty = this.lazy // for lazy watchers
    this.deps = []
    this.newDeps = []
    this.depIds = new Set()
    this.newDepIds = new Set()
    this.expression =
      process.env.NODE_ENV !== "production" ? expOrFn.toString() : ""
    // parse expression for getter
    /*把表達(dá)式expOrFn解析成getter*/
    if (typeof expOrFn === "function") {
      this.getter = expOrFn
    } else {
      this.getter = parsePath(expOrFn)
      if (!this.getter) {
        this.getter = function() {}
        process.env.NODE_ENV !== "production" &&
          warn(
            `Failed watching path: "${expOrFn}" ` +
              "Watcher only accepts simple dot-delimited paths. " +
              "For full control, use a function instead.",
            vm
          )
      }
    }
    this.value = this.lazy ? undefined : this.get()
  }

  /**
   * Evaluate the getter, and re-collect dependencies.
   */
  /*獲得getter的值并且重新進(jìn)行依賴收集*/
  get() {
    /*將自身watcher觀察者實(shí)例設(shè)置給Dep.target,用以依賴收集。*/
    pushTarget(this)
    let value
    const vm = this.vm

    /*
    執(zhí)行了getter操作,看似執(zhí)行了渲染操作,其實(shí)是執(zhí)行了依賴收集。
    在將Dep.target設(shè)置為自生觀察者實(shí)例以后,執(zhí)行g(shù)etter操作。
    譬如說現(xiàn)在的的data中可能有a、b、c三個(gè)數(shù)據(jù),getter渲染需要依賴a跟c,
    那么在執(zhí)行g(shù)etter的時(shí)候就會(huì)觸發(fā)a跟c兩個(gè)數(shù)據(jù)的getter函數(shù),
    在getter函數(shù)中即可判斷Dep.target是否存在然后完成依賴收集,
    將該觀察者對象放入閉包中的Dep的subs中去。
    */
    if (this.user) {
      try {
        value = this.getter.call(vm, vm)
      } catch (e) {
        handleError(e, vm, `getter for watcher "${this.expression}"`)
      }
    } else {
      value = this.getter.call(vm, vm)
    }
    // "touch" every property so they are all tracked as
    // dependencies for deep watching
    /*如果存在deep,則觸發(fā)每個(gè)深層對象的依賴,追蹤其變化*/
    if (this.deep) {
      /*遞歸每一個(gè)對象或者數(shù)組,觸發(fā)它們的getter,使得對象或數(shù)組的每一個(gè)成員都被依賴收集,形成一個(gè)“深(deep)”依賴關(guān)系*/
      traverse(value)
    }

    /*將觀察者實(shí)例從target棧中取出并設(shè)置給Dep.target*/
    popTarget()
    this.cleanupDeps()
    return value
  }

  /**
   * Add a dependency to this directive.
   */
  /*添加一個(gè)依賴關(guān)系到Deps集合中*/
  addDep(dep: Dep) {
    const id = dep.id
    if (!this.newDepIds.has(id)) {
      this.newDepIds.add(id)
      this.newDeps.push(dep)
      if (!this.depIds.has(id)) {
        dep.addSub(this)
      }
    }
  }

  /**
   * Clean up for dependency collection.
   */
  /*清理依賴收集*/
  cleanupDeps() {
    /*移除所有觀察者對象*/
    let i = this.deps.length
    while (i--) {
      const dep = this.deps[i]
      if (!this.newDepIds.has(dep.id)) {
        dep.removeSub(this)
      }
    }
    let tmp = this.depIds
    this.depIds = this.newDepIds
    this.newDepIds = tmp
    this.newDepIds.clear()
    tmp = this.deps
    this.deps = this.newDeps
    this.newDeps = tmp
    this.newDeps.length = 0
  }

  /**
   * Subscriber interface.
   * Will be called when a dependency changes.
   */
  /*
  調(diào)度者接口,當(dāng)依賴發(fā)生改變的時(shí)候進(jìn)行回調(diào)。
  */
  update() {
    /* istanbul ignore else */
    if (this.lazy) {
      this.dirty = true
    } else if (this.sync) {
      /*同步則執(zhí)行run直接渲染視圖*/
      this.run()
    } else {
      /*異步推送到觀察者隊(duì)列中,由調(diào)度者調(diào)用。*/
      queueWatcher(this)
    }
  }

  /**
   * Scheduler job interface.
   * Will be called by the scheduler.
   */
  /*
        調(diào)度者工作接口,將被調(diào)度者回調(diào)。
        */
  run() {
    if (this.active) {
      const value = this.get()
      if (
        value !== this.value ||
        // Deep watchers and watchers on Object/Arrays should fire even
        // when the value is the same, because the value may
        // have mutated.
        /*
          即便值相同,擁有Deep屬性的觀察者以及在對象/數(shù)組上的觀察者應(yīng)該被觸發(fā)更新,因?yàn)樗鼈兊闹悼赡馨l(fā)生改變。
        */
        isObject(value) ||
        this.deep
      ) {
        // set new value
        const oldValue = this.value
        /*設(shè)置新的值*/
        this.value = value

        /*觸發(fā)回調(diào)渲染視圖*/
        if (this.user) {
          try {
            this.cb.call(this.vm, value, oldValue)
          } catch (e) {
            handleError(e, this.vm, `callback for watcher "${this.expression}"`)
          }
        } else {
          this.cb.call(this.vm, value, oldValue)
        }
      }
    }
  }

  /**
   * Evaluate the value of the watcher.
   * This only gets called for lazy watchers.
   */
  /*獲取觀察者的值*/
  evaluate() {
    this.value = this.get()
    this.dirty = false
  }

  /**
   * Depend on all deps collected by this watcher.
   */
  /*收集該watcher的所有deps依賴*/
  depend() {
    let i = this.deps.length
    while (i--) {
      this.deps[i].depend()
    }
  }

  /**
   * Remove self from all dependencies" subscriber list.
   */
  /*將自身從所有依賴收集訂閱列表刪除*/
  teardown() {
    if (this.active) {
      // remove self from vm"s watcher list
      // this is a somewhat expensive operation so we skip it
      // if the vm is being destroyed.
      /*從vm實(shí)例的觀察者列表中將自身移除,由于該操作比較耗費(fèi)資源,所以如果vm實(shí)例正在被銷毀則跳過該步驟。*/
      if (!this.vm._isBeingDestroyed) {
        remove(this.vm._watchers, this)
      }
      let i = this.deps.length
      while (i--) {
        this.deps[i].removeSub(this)
      }
      this.active = false
    }
  }
}

通過上面對 vue 的響應(yīng)系統(tǒng)的 學(xué)習(xí),就可以了解到這個(gè)發(fā)布訂閱模式就是這樣的:

Dep 負(fù)責(zé)收集所有相關(guān)的的訂閱者 Watcher ,具體誰不用管,具體有多少也不用管,只需要根據(jù) target 指向的計(jì)算去收集訂閱其消息的 Watcher 即可,然后做好消息發(fā)布 notify 即可。

Watcher 負(fù)責(zé)訂閱 Dep ,并在訂閱的時(shí)候讓 Dep 進(jìn)行收集,接收到 Dep 發(fā)布的消息時(shí),做好其 update 操作即可。

3、vue 中更多的應(yīng)用

vue 中還有個(gè)組件之間的時(shí)間傳遞也是用到了發(fā)布訂閱模式。
$emit 負(fù)責(zé)發(fā)布消息, $on 負(fù)責(zé)消費(fèi)消息(執(zhí)行 cbs 里面的事件)

Vue.prototype.$on = function(
  event: string | Array,
  fn: Function
): Component {
  const vm: Component = this
  if (Array.isArray(event)) {
    for (let i = 0, l = event.length; i < l; i++) {
      this.$on(event[i], fn)
    }
  } else {
    ;(vm._events[event] || (vm._events[event] = [])).push(fn)
  }
  return vm
}

Vue.prototype.$emit = function(event: string): Component {
  const vm: Component = this
  let cbs = vm._events[event]
  if (cbs) {
    cbs = cbs.length > 1 ? toArray(cbs) : cbs
    const args = toArray(arguments, 1)
    for (let i = 0, l = cbs.length; i < l; i++) {
      cbs[i].apply(vm, args)
    }
  }
  return vm
}
總結(jié)

本文通過對 vue 相關(guān)源碼的學(xué)習(xí),了解了發(fā)布訂閱模式(觀察者模式)的概念和應(yīng)用。還了解了該模式的 一些優(yōu)缺點(diǎn):

時(shí)間上的解耦,對象之間的解耦。

創(chuàng)建訂閱者本身會(huì)消耗一定的時(shí)間和內(nèi)存,并且訂閱者訂閱一個(gè)消息后,該消息一直不發(fā)生的話,那么該訂閱者 會(huì)一直存在在內(nèi)存中

感謝

從源碼角度再看數(shù)據(jù)綁定

《javascript 設(shè)計(jì)模式與開發(fā)實(shí)踐》

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107602.html

相關(guān)文章

  • 源碼解析 —— Vue響應(yīng)式數(shù)據(jù)流

    摘要:下面我們會(huì)向大家解釋清楚為什么這個(gè)這么重要,以及它和的響應(yīng)式數(shù)據(jù)流有什么關(guān)系。源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應(yīng)式數(shù)據(jù)流。總結(jié)講到這里大家應(yīng)該都能夠明白的響應(yīng)式數(shù)據(jù)流是如何實(shí)現(xiàn)的。 Vue、React介紹 目前前端社區(qū)比較推崇的框架有Vue 和 React,公司內(nèi)部許多端都自發(fā)的將原有的老技術(shù)方案(widget + jQuery)遷移到 Vue / React上了。我...

    LuDongWei 評論0 收藏0
  • vue.js響應(yīng)式原理解析與實(shí)現(xiàn)

    摘要:今天,就我們就來一步步解析響應(yīng)式的原理,并且來實(shí)現(xiàn)一個(gè)簡單的。當(dāng)然,這個(gè)也只是一個(gè)簡單的,來說明響應(yīng)式的原理,真實(shí)的源碼會(huì)更加復(fù)雜,因?yàn)榧恿撕芏嗥渌壿嫛=酉聛砦铱赡軙?huì)將其與聯(lián)系起來,實(shí)現(xiàn)和語法。 從很久之前就已經(jīng)接觸過了angularjs了,當(dāng)時(shí)就已經(jīng)了解到,angularjs是通過臟檢查來實(shí)現(xiàn)數(shù)據(jù)監(jiān)測以及頁面更新渲染。之后,再接觸了vue.js,當(dāng)時(shí)也一度很好奇vue.js是如何監(jiān)...

    Shihira 評論0 收藏0
  • 訂閱發(fā)布模式和觀察者模式的區(qū)別

    摘要:或許以前認(rèn)為訂閱發(fā)布模式是觀察者模式的一種別稱,但是發(fā)展至今,概念已經(jīng)有了不少區(qū)別。參考文章訂閱發(fā)布模式和觀察者模式真的不一樣 首選我們需要先了解兩者的定義和實(shí)現(xiàn)的方式,才能更好的區(qū)分兩者的不同點(diǎn)。 或許以前認(rèn)為訂閱發(fā)布模式是觀察者模式的一種別稱,但是發(fā)展至今,概念已經(jīng)有了不少區(qū)別。 訂閱發(fā)布模式 在軟件架構(gòu)中,發(fā)布-訂閱是一種消息范式,消息的發(fā)送者(稱為發(fā)布者)不會(huì)將消息直接發(fā)送給特...

    ysl_unh 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<