成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[面試專題]JS設(shè)計(jì)模式

cnTomato / 1928人閱讀

摘要:設(shè)計(jì)模式發(fā)布訂閱模式這種設(shè)計(jì)模式可以大大降低程序模塊之間的耦合度,便于更加靈活的擴(kuò)展和維護(hù)。代理模式使得代理對(duì)象控制具體對(duì)象的引用。該模式使一個(gè)類的實(shí)例化延遲到了子類。

JS設(shè)計(jì)模式 發(fā)布訂閱模式:

這種設(shè)計(jì)模式可以大大降低程序模塊之間的耦合度,便于更加靈活的擴(kuò)展和維護(hù)。

// 一個(gè)播放器類
class Player {

  constructor() {
    // 初始化觀察者列表
    this.watchers = {}

    // 模擬2秒后發(fā)布一個(gè)"play"事件
    setTimeout(() => {
      this._publish("play", true)
    }, 2000)

    // 模擬4秒后發(fā)布一個(gè)"pause"事件
    setTimeout(() => {
      this._publish("pause", true)
    }, 4000)
  }

  // 發(fā)布事件
  _publish(event, data) {
    if (this.watchers[event] && this.watchers[event].length) {
      this.watchers[event].forEach(callback => callback.bind(this)(data))
    }
  }

  // 訂閱事件
  subscribe(event, callback) {
    this.watchers[event] = this.watchers[event] || []
    this.watchers[event].push(callback)
  }

  // 退訂事件
  unsubscribe(event = null, callback = null) {
    // 如果傳入指定事件函數(shù),則僅退訂此事件函數(shù)
    if (callback&&event) {
      if (this.watchers[event] && this.watchers[event].length) {
        this.watchers[event].splice(this.watchers[event].findIndex(cb => Object.is(cb, callback)), 1)
      }

    // 如果僅傳入事件名稱,則退訂此事件對(duì)應(yīng)的所有的事件函數(shù)
    } else if (event) {
      this.watchers[event] = []

    // 如果未傳入任何參數(shù),則退訂所有事件
    } else {
      this.watchers = {}
    }
  }
}

// 實(shí)例化播放器
const player = new Player()
console.log(player)

// 播放事件回調(diào)函數(shù)1
const onPlayerPlay1 = function(data) {
  console.log("1: Player is play, the `this` context is current player", this, data)
}

// 播放事件回調(diào)函數(shù)2
const onPlayerPlay2 = data => {
  console.log("2: Player is play", data)
}

// 暫停事件回調(diào)函數(shù)
const onPlayerPause = data => {
  console.log("Player is pause", data)
}

// 加載事件回調(diào)函數(shù)
const onPlayerLoaded = data => {
  console.log("Player is loaded", data)
}

// 可訂閱多個(gè)不同事件
player.subscribe("play", onPlayerPlay1)
player.subscribe("play", onPlayerPlay2)
player.subscribe("pause", onPlayerPause)
player.subscribe("loaded", onPlayerLoaded)

// 可以退訂指定訂閱事件
player.unsubscribe("play", onPlayerPlay2)
// 退訂指定事件名稱下的所有訂閱事件
player.unsubscribe("play")
// 退訂所有訂閱事件
player.unsubscribe()

// 可以在外部手動(dòng)發(fā)出事件(真實(shí)生產(chǎn)場(chǎng)景中,發(fā)布特性一般為類內(nèi)部私有方法)
player._publish("loaded", true)
中介者模式 Mediator Pattern:

觀察者模式通過維護(hù)一堆列表來管理對(duì)象間的多對(duì)多關(guān)系,中介者模式通過統(tǒng)一接口來維護(hù)一對(duì)多關(guān)系,且通信者之間不需要知道彼此之間的關(guān)系,只需要約定好API即可。

// 汽車
class Bus {

  constructor() {

    // 初始化所有乘客
    this.passengers = {}
  }

  // 發(fā)布廣播
  broadcast(passenger, message = passenger) {
    // 如果車上有乘客
    if (Object.keys(this.passengers).length) {

      // 如果是針對(duì)某個(gè)乘客發(fā)的,就多帶帶給他聽
      if (passenger.id && passenger.listen) {

        // 乘客他愛聽不聽
        if (this.passengers[passenger.id]) {
          this.passengers[passenger.id].listen(message)
        }

      // 不然就廣播給所有乘客
      } else {
        Object.keys(this.passengers).forEach(passenger => {
          if (this.passengers[passenger].listen) {
            this.passengers[passenger].listen(message)
          }
        })
      }
    }
  }

  // 乘客上車
  aboard(passenger) {
    this.passengers[passenger.id] = passenger
  }

  // 乘客下車
  debus(passenger) {
    this.passengers[passenger.id] = null
    delete this.passengers[passenger.id]
    console.log(`乘客${passenger.id}下車`)
  }

  // 開車
  start() {
    this.broadcast({ type: 1, content: "前方無障礙,開車!Over"})
  }

  // 停車
  end() {
    this.broadcast({ type: 2, content: "老司機(jī)翻車,停車!Over"})
  }
}

// 乘客
class Passenger {

  constructor(id) {
    this.id = id
  }

  // 聽廣播
  listen(message) {
    console.log(`乘客${this.id}收到消息`, message)
    // 乘客發(fā)現(xiàn)停車了,于是自己下車
    if (Object.is(message.type, 2)) {
      this.debus()
    }
  }

  // 下車
  debus() {
    console.log(`我是乘客${this.id},我現(xiàn)在要下車`, bus)
    bus.debus(this)
  }
}

// 創(chuàng)建一輛汽車
const bus = new Bus()

// 創(chuàng)建兩個(gè)乘客
const passenger1 = new Passenger(1)
const passenger2 = new Passenger(2)

// 倆乘客分別上車
bus.aboard(passenger1)
bus.aboard(passenger2)

// 2秒后開車
setTimeout(bus.start.bind(bus), 2000)

// 3秒時(shí)司機(jī)發(fā)現(xiàn)2號(hào)乘客沒買票,2號(hào)乘客被驅(qū)逐下車
setTimeout(() => {
  bus.broadcast(passenger2, { type: 3, content: "同志你好,你沒買票,請(qǐng)下車!" })
  bus.debus(passenger2)
}, 3000)

// 4秒后到站停車
setTimeout(bus.end.bind(bus), 3600)

// 6秒后再開車,車上已經(jīng)沒乘客了
setTimeout(bus.start.bind(bus), 6666)
代理模式 Proxy Pattern:

為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。
代理模式使得代理對(duì)象控制具體對(duì)象的引用。代理幾乎可以是任何對(duì)象:文件,資源,內(nèi)存中的對(duì)象,或者是一些難以復(fù)制的東西。

ES6中的Proxy對(duì)象

const target = {}
const handler = {
    get(target, property) {
        if (property in target) {
            return target[property]
        } else {
            throw new ReferenceError("Property "" + property + "" does not exist.")
        }
    }
}
const p = new Proxy(target, {})
p.a = 3  // 被轉(zhuǎn)發(fā)到代理的操作
console.log(p.c) //
單例模式 Singleton Pattern:

保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)(調(diào)用一個(gè)類,任何時(shí)候返回的都是同一個(gè)實(shí)例)。

實(shí)現(xiàn)方法:使用一個(gè)變量來標(biāo)志當(dāng)前是否已經(jīng)為某個(gè)類創(chuàng)建過對(duì)象,如果創(chuàng)建了,則在下一次獲取該類的實(shí)例時(shí),直接返回之前創(chuàng)建的對(duì)象,否則就創(chuàng)建一個(gè)對(duì)象。

// 類數(shù)實(shí)例:
class Singleton {
  constructor(name) {
    this.name = name
    this.instance = null   // 
  }
  getName() {
    alert(this.name)
  }
  static getInstance(name) {
    if (!this.instance) {
      this.instance = new Singleton(name)
    }
    return this.instance
  }
}
const ins = new Singleton("hhhh")
const instanceA = Singleton.getInstance("seven1")
const instanceB = Singleton.getInstance("seven2")
//閉包包裝實(shí)例:
const SingletonP = (function() {
  let instance
  return class Singleton {

    constructor(name) {
      if (instance) {
        return instance
      } else {
        this.init(name)
        instance = this
        return this
      }
    }

    init(name) {
      this.name = name
      console.log("已初始化")
    }
  }
})()

const instanceA = new SingletonP("seven1")
const instanceB = new SingletonP("seven2")
// ES5 iife
var SingletonTester = (function () {
    function Singleton(args) {
        var args = args || {};
        //設(shè)置name參數(shù)
        this.name = "SingletonTester";
    }
    //實(shí)例容器
    var instance;
    return {
        name: "SingletonTester",
        getInstance: function (args) {
            if (instance === undefined) {
                instance = new Singleton(args);
            }
            return instance;
        }
    };
})();

var singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // 輸出 5 
// 構(gòu)造函數(shù)的屬性
function Universe() {
    if (typeof Universe.instance === "object") {
        return Universe.instance;
    }
    this.start_time = 0;
    this.bang = "Big";
    Universe.instance = this;
}
// 測(cè)試
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
// 重寫構(gòu)造函數(shù)
function Universe() {
    var instance = this;
    // 其它內(nèi)容
    this.start_time = 0;
    this.bang = "Big";
    // 重寫構(gòu)造函數(shù)
    Universe = function () {
        return instance;
    };
}
// 測(cè)試
var uni = new Universe();
var uni2 = new Universe();
uni.bang = "123";
console.log(uni === uni2); // true
console.log(uni2.bang); // 123
工廠模式 Factory Pattern:

工廠模式定義一個(gè)用于創(chuàng)建對(duì)象的接口,這個(gè)接口由子類決定實(shí)例化哪一個(gè)類。該模式使一個(gè)類的實(shí)例化延遲到了子類。而子類可以重寫接口方法以便創(chuàng)建的時(shí)候指定自己的對(duì)象類型。

簡(jiǎn)單說:假如我們想在網(wǎng)頁(yè)面里插入一些元素,而這些元素類型不固定,可能是圖片、鏈接、文本,根據(jù)工廠模式的定義,在工廠模式下,工廠函數(shù)只需接受我們要?jiǎng)?chuàng)建的元素的類型,其他的工廠函數(shù)幫我們處理。

// 文本工廠
class Text {
    constructor(text) {
        this.text = text
    }
    insert(where) {
        const txt = document.createTextNode(this.text)
        where.appendChild(txt)
    }
}

// 鏈接工廠
class Link {
    constructor(url) {
        this.url = url
    }
    insert(where) {
        const link = document.createElement("a")
        link.href = this.url
        link.appendChild(document.createTextNode(this.url))
        where.appendChild(link)
    }
}

// 圖片工廠
class Image {
    constructor(url) {
        this.url = url
    }
    insert(where) {
        const img = document.createElement("img")
        img.src = this.url
        where.appendChild(img)
    }
}

// DOM工廠
class DomFactory {

  constructor(type) {
    return new (this[type]())
  }

  // 各流水線
  link() { return Link }
  text() { return Text }
  image() { return Image }
}

// 創(chuàng)建工廠
const linkFactory = new DomFactory("link")
const textFactory = new DomFactory("text")

linkFactory.url = "https://surmon.me"
linkFactory.insert(document.body)

textFactory.text = "HI! I am surmon."
textFactory.insert(document.body)
裝飾者模式 Decorative Pattern:

裝飾者(decorator)模式能夠在不改變對(duì)象自身的基礎(chǔ)上,在程序運(yùn)行期間給對(duì)像動(dòng)態(tài)的添加職責(zé)(方法或?qū)傩裕?。與繼承相比,裝飾者是一種更輕便靈活的做法。

簡(jiǎn)單說:可以動(dòng)態(tài)的給某個(gè)對(duì)象添加額外的職責(zé),而不會(huì)影響從這個(gè)類中派生的其它對(duì)象。

ES7裝飾器
function isAnimal(target) {
    target.isAnimal = true
    return target
}

// 裝飾器
@isAnimal
class Cat {
    // ...
}
console.log(Cat.isAnimal)    // true



作用于類屬性的裝飾器:

function readonly(target, name, descriptor) {
    discriptor.writable = false
    return discriptor
}

class Cat {
    @readonly
    say() {
        console.log("meow ~")
    }
}

var kitty = new Cat()
kitty.say = function() {
    console.log("woof !")
}
kitty.say()    // meow ~

參考:
輸入理解js系列
來自ES6入門實(shí)踐

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85042.html

相關(guān)文章

  • [面試專題]一線互聯(lián)網(wǎng)大廠面試總結(jié)

    摘要:道阻且長(zhǎng)啊前端面試總結(jié)前端面試筆試面試騰訊一面瀏覽器工作原理瀏覽器的主要組件包括用戶界面包括地址欄后退前進(jìn)按鈕書簽?zāi)夸洖g覽器引擎用來查詢及操作渲染引擎的接口渲染引擎渲染界面和是基于兩種渲染引擎構(gòu)建的,使用自主研發(fā)的渲染引擎,和都使用網(wǎng)絡(luò)用來 道阻且長(zhǎng)啊TAT(前端面試總結(jié)) 前端 面試 筆試 面試 騰訊一面 1.瀏覽器工作原理 瀏覽器的主要組件包括: 用戶界面- 包括地址欄、后退/前...

    lemanli 評(píng)論0 收藏0
  • [面試專題]一線互聯(lián)網(wǎng)大廠面試總結(jié)

    摘要:道阻且長(zhǎng)啊前端面試總結(jié)前端面試筆試面試騰訊一面瀏覽器工作原理瀏覽器的主要組件包括用戶界面包括地址欄后退前進(jìn)按鈕書簽?zāi)夸洖g覽器引擎用來查詢及操作渲染引擎的接口渲染引擎渲染界面和是基于兩種渲染引擎構(gòu)建的,使用自主研發(fā)的渲染引擎,和都使用網(wǎng)絡(luò)用來 道阻且長(zhǎng)啊TAT(前端面試總結(jié)) 前端 面試 筆試 面試 騰訊一面 1.瀏覽器工作原理 瀏覽器的主要組件包括: 用戶界面- 包括地址欄、后退/前...

    xfee 評(píng)論0 收藏0
  • [面試專題]一線互聯(lián)網(wǎng)大廠面試總結(jié)

    摘要:道阻且長(zhǎng)啊前端面試總結(jié)前端面試筆試面試騰訊一面瀏覽器工作原理瀏覽器的主要組件包括用戶界面包括地址欄后退前進(jìn)按鈕書簽?zāi)夸洖g覽器引擎用來查詢及操作渲染引擎的接口渲染引擎渲染界面和是基于兩種渲染引擎構(gòu)建的,使用自主研發(fā)的渲染引擎,和都使用網(wǎng)絡(luò)用來 道阻且長(zhǎng)啊TAT(前端面試總結(jié)) 前端 面試 筆試 面試 騰訊一面 1.瀏覽器工作原理 瀏覽器的主要組件包括: 用戶界面- 包括地址欄、后退/前...

    leap_frog 評(píng)論0 收藏0
  • [面試專題]js之面向?qū)ο?OOP)

    摘要:之面向?qū)ο髮?duì)象類型數(shù)據(jù)類型分六類簡(jiǎn)單類型五種復(fù)雜類型其中也屬于基本類型。 js之面向?qū)ο?OOP) js對(duì)象類型(Object) js數(shù)據(jù)類型分六類,簡(jiǎn)單類型:Undefined,Null,Bollean,Number,String五種,復(fù)雜類型:Object.其中Undefined、Null、Boolean、Number也屬于基本類型。Object、Array和Function則屬...

    andycall 評(píng)論0 收藏0
  • [面試專題]Vue.js 2.0 獨(dú)立構(gòu)建和運(yùn)行時(shí)構(gòu)建的區(qū)別

    摘要:獨(dú)立構(gòu)建和運(yùn)行時(shí)構(gòu)建的區(qū)別標(biāo)簽空格分隔未分類在使用時(shí),有獨(dú)立構(gòu)建和運(yùn)行時(shí)構(gòu)建兩種版本可供選擇。運(yùn)行時(shí)構(gòu)建不包括模板編譯,不支持選項(xiàng)。這就形成了獨(dú)立構(gòu)建編譯器運(yùn)行時(shí)和運(yùn)行時(shí)構(gòu)建僅運(yùn)行時(shí)。 Vue.js 2.0 獨(dú)立構(gòu)建和運(yùn)行時(shí)構(gòu)建的區(qū)別 標(biāo)簽(空格分隔): 未分類 在使用 Vue.js 2.0 時(shí),有獨(dú)立構(gòu)建(standalone)和運(yùn)行時(shí)構(gòu)建(runtime-only)兩種版本可供選...

    李義 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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