日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

JavaScript設(shè)計(jì)模式之觀察者模式與發(fā)布訂閱模式詳解

瀏覽:266日期:2023-10-30 15:13:27

本文實(shí)例講述了JavaScript設(shè)計(jì)模式之觀察者模式與發(fā)布訂閱模式。分享給大家供大家參考,具體如下:

學(xué)習(xí)了一段時(shí)間設(shè)計(jì)模式,當(dāng)學(xué)到觀察者模式和發(fā)布訂閱模式的時(shí)候遇到了很大的問(wèn)題,這兩個(gè)模式有點(diǎn)類似,有點(diǎn)傻傻分不清楚,博客起因如此,開(kāi)始對(duì)觀察者和發(fā)布訂閱開(kāi)始了Google之旅。對(duì)整個(gè)學(xué)習(xí)過(guò)程做一個(gè)簡(jiǎn)單的記錄。

觀察者模式

當(dāng)對(duì)象間存在一對(duì)多關(guān)系時(shí),則使用觀察者模式(Observer Pattern)。比如,當(dāng)一個(gè)對(duì)象被修改時(shí),則會(huì)自動(dòng)通知它的依賴對(duì)象。觀察者模式屬于行為型模式。在觀察模式中共存在兩個(gè)角色觀察者(Observer)與被觀察者(Subject),然而觀察者模式在軟件設(shè)計(jì)中是一個(gè)對(duì)象,維護(hù)一個(gè)依賴列表,當(dāng)任何狀態(tài)發(fā)生改變自動(dòng)通知它們。

其實(shí)觀察者模式是一個(gè)或多個(gè)觀察者對(duì)目標(biāo)的狀態(tài)感興趣,它們通過(guò)將自己依附在目標(biāo)對(duì)象之上以便注冊(cè)所感興趣的內(nèi)容。目標(biāo)狀態(tài)發(fā)生改變并且觀察者可能對(duì)這些改變感興趣,就會(huì)發(fā)送一個(gè)通知消息,調(diào)用每個(gè)觀察者的更新方法。當(dāng)觀察者不再對(duì)目標(biāo)狀態(tài)感興趣時(shí),它們可以簡(jiǎn)單的將自己從中分離。

在觀察者模式中一共分為這么幾個(gè)角色:

Subject:維護(hù)一系列觀察者,方便添加或刪除觀察者 Observer:為那些在目標(biāo)狀態(tài)發(fā)生改變時(shí)需要獲得通知的對(duì)象提供一個(gè)更新接口 ConcreteSuject:狀態(tài)發(fā)生改變時(shí),想Observer發(fā)送通知,存儲(chǔ)ConcreteObserver的狀態(tài) ConcreteObserver:具體的觀察者舉例

舉一個(gè)生活中的例子,公司老板可以為下面的工作人員分配認(rèn)為,如果老板作為被觀察者而存在,那么下面所屬的那些員工則就作為觀察者而存在,為工作人員分配的任務(wù)來(lái)通知下面的工作人員應(yīng)該去做哪些工作。

通過(guò)上面的例子可以對(duì)觀察者模式有一個(gè)簡(jiǎn)單的認(rèn)知,接下來(lái)結(jié)合下面的這張圖來(lái)再次分析一下上面的例子。

如果Subject = 老板的話,那么Observer N = 工作人員,如果細(xì)心觀察的話會(huì)發(fā)現(xiàn)下圖中莫名到的多了一個(gè)notify(),那么上述例子中的工作就是notify()。

JavaScript設(shè)計(jì)模式之觀察者模式與發(fā)布訂閱模式詳解

既然各個(gè)關(guān)系已經(jīng)屢清楚了,下面通過(guò)代碼來(lái)實(shí)現(xiàn)一下上述的例子:

// 觀察者隊(duì)列class ObserverList{ constructor(){ this.observerList = {}; } Add(obj,type = 'any'){ if(!this.observerList[type]){ this.observerList[type] = []; } this.observerList[type].push(obj); } Count(type = 'any'){ return this.observerList[type].length; } Get(index,type = 'any'){ let len = this.observerList[type].length; if(index > -1 && index < len){ return this.observerList[type][index] } } IndexOf(obj,startIndex,type = 'any'){ let i = startIndex, pointer = -1; let len = this.observerList[type].length; while(i < len){ if(this.observerList[type][i] === obj){pointer = i; } i++; } return pointer; } RemoveIndexAt(index,type = 'any'){ let len = this.observerList[type].length; if(index === 0){ this.observerList[type].shift(); } else if(index === len-1){ this.observerList[type].pop(); } else{ this.observerList[type].splice(index,1); } }}// 老板class Boos { constructor(){ this.observers = new ObserverList(); } AddObserverList(observer,type){ this.observers.Add(observer,type); } RemoveObserver(oberver,type){ let i = this.observers.IndexOf(oberver,0,type); (i != -1) && this.observers.RemoveIndexAt(i,type); } Notify(type){ let oberverCont = this.observers.Count(type); for(let i=0;i<oberverCont;i++){ let emp = this.observers.Get(i,type); emp && emp(type); } }}class Employees { constructor(name){ this.name = name; } getName(){ return this.name; }}class Work { married(name){ console.log(`${name}上班`); } unemployment(name){ console.log(`${name}出差`); } writing(name){ console.log(`${name}寫(xiě)作`); } writeCode(name){ console.log(`${name}打代碼`); }}let MyBoos = new Boos();let work = new Work();let aaron = new Employees('Aaron');let angie = new Employees('Angie');let aaronName = aaron.getName();let angieName = angie.getName();MyBoos.AddObserverList(work.married,aaronName);MyBoos.AddObserverList(work.writeCode,aaronName);MyBoos.AddObserverList(work.writing,aaronName);MyBoos.RemoveObserver(work.writing,aaronName);MyBoos.Notify(aaronName);MyBoos.AddObserverList(work.married,angieName);MyBoos.AddObserverList(work.unemployment,angieName);MyBoos.Notify(angieName);// Aaron上班// Aaron打代碼// Angie上班// Angie出差

代碼里面完全遵循了流程圖,Boos類作為被觀察者而存在,Staff作為觀察者,通過(guò)Work兩者做關(guān)聯(lián)。

如果相信的閱讀上述代碼的話可以出,其實(shí)觀察者的核心代碼就是peopleList這個(gè)對(duì)象,這個(gè)對(duì)象里面存放了N多個(gè)Array數(shù)組,通過(guò)run方法觸發(fā)觀察者的notify隊(duì)列。觀察者模式主要解決的問(wèn)題就是,一個(gè)對(duì)象狀態(tài)改變給其他對(duì)象通知的問(wèn)題,而且要考慮到易用和低耦合,保證高度的協(xié)作。當(dāng)我們?cè)谧龀绦蛟O(shè)計(jì)的時(shí)候,當(dāng)一個(gè)目標(biāo)對(duì)象的狀態(tài)發(fā)生改變,所有的觀察者對(duì)象都將得到通知,進(jìn)行廣播通知的時(shí)候,就可以使用觀察者模式啦。

優(yōu)點(diǎn) 觀察者和被觀察者是抽象耦合的。 建立一套觸發(fā)機(jī)制。缺點(diǎn) 如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。 如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話,觀察目標(biāo)會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,可能導(dǎo)致系統(tǒng)崩潰。 觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對(duì)象是怎么發(fā)生變化的,而僅僅只是知道觀察目標(biāo)發(fā)生了變化。小結(jié)

對(duì)于觀察者模式在被觀察者中有一個(gè)用于存儲(chǔ)觀察者對(duì)象的list隊(duì)列,通過(guò)統(tǒng)一的方法觸發(fā),目標(biāo)和觀察者是基類,目標(biāo)提供維護(hù)觀察者的一系列方法,觀察者提供更新接口。具體觀察者和具體目標(biāo)繼承各自的基類,然后具體觀察者把自己注冊(cè)到具體目標(biāo)里,在具體目標(biāo)發(fā)生變化時(shí)候,調(diào)度觀察者的更新方法。

發(fā)布/訂閱模式

在發(fā)布訂閱模式上卡了很久,但是廢了好長(zhǎng)時(shí)間沒(méi)有搞明白,也不知道自己的疑問(wèn)在哪,于是就瘋狂Google不斷地翻閱找到自己的疑問(wèn),個(gè)人覺(jué)得如果想要搞明白發(fā)布訂閱模式首先要搞明白誰(shuí)是發(fā)布者,誰(shuí)是訂閱者。

發(fā)布訂閱:在軟件架構(gòu)中,發(fā)布-訂閱是一種消息范式,消息的發(fā)送者(稱為發(fā)布者)不會(huì)將消息直接發(fā)送給特定的接收者(稱為訂閱者)。而是將發(fā)布的消息分為不同的類別,無(wú)需了解哪些訂閱者(如果有的話)可能存在。同樣的,訂閱者可以表達(dá)對(duì)一個(gè)或多個(gè)類別的興趣,只接收感興趣的消息,無(wú)需了解哪些發(fā)布者(如果有的話)存在。-- 維基百科

看了半天沒(méi)整明白(✿◡‿◡),慚愧...于是,學(xué)習(xí)的路途不能止步,繼續(xù)...

大概很多人都和我一樣,覺(jué)得發(fā)布訂閱模式里的Publisher,就是觀察者模式里的Subject,而Subscriber,就是Observer。Publisher變化時(shí),就主動(dòng)去通知Subscriber。其實(shí)并不是。在發(fā)布訂閱模式里,發(fā)布者,并不會(huì)直接通知訂閱者,換句話說(shuō),發(fā)布者和訂閱者,彼此互不相識(shí)。互不相識(shí)?那他們之間如何交流?

答案是,通過(guò)第三者,也就是在消息隊(duì)列里面,我們常說(shuō)的經(jīng)紀(jì)人Broker。

發(fā)布者只需告訴Broker,我要發(fā)的消息,topic是AAA,訂閱者只需告訴Broker,我要訂閱topic是AAA的消息,于是,當(dāng)Broker收到發(fā)布者發(fā)過(guò)來(lái)消息,并且topic是AAA時(shí),就會(huì)把消息推送給訂閱了topic是AAA的訂閱者。當(dāng)然也有可能是訂閱者自己過(guò)來(lái)拉取,看具體實(shí)現(xiàn)。

也就是說(shuō),發(fā)布訂閱模式里,發(fā)布者和訂閱者,不是松耦合,而是完全解耦的。

JavaScript設(shè)計(jì)模式之觀察者模式與發(fā)布訂閱模式詳解

通過(guò)上面的描述終于有了一些眉目,再舉一個(gè)生活中的例子,就拿微信公眾號(hào)來(lái)說(shuō),每次微信公眾號(hào)推送消息并不是一下子推送給微信的所有用戶,而是選擇性的推送給那些已經(jīng)訂閱了該公眾號(hào)的人。

老規(guī)矩吧,用代碼實(shí)現(xiàn)一下:

class Utils { constructor(){ this.observerList = {}; } Add(obj,type = 'any'){ if(!this.observerList[type]){ this.observerList[type] = []; } this.observerList[type].push(obj); } Count(type = 'any'){ return this.observerList[type].length; } Get(index,type = 'any'){ let len = this.observerList[type].length; if(index > -1 && index < len){ return this.observerList[type][index] } } IndexOf(obj,startIndex,type = 'any'){ let i = startIndex, pointer = -1; let len = this.observerList[type].length; while(i < len){ if(this.observerList[type][i] === obj){ pointer = i; } i++; } return pointer; }}// 訂閱者class Subscribe extends Utils {};// 發(fā)布者class Publish extends Utils {};// 中轉(zhuǎn)站class Broker { constructor(){ this.publish = new Publish(); this.subscribe = new Subscribe(); } // 訂閱 Subscribe(fn,key){ this.subscribe.Add(fn,key); } // 發(fā)布 Release(fn,key){ this.publish.Add(fn,key); } Run(key = 'any'){ let publishList = this.publish.observerList; let subscribeList = this.subscribe.observerList; if(!publishList[key] || !subscribeList[key]) throw 'No subscribers or published messages'; let pub = publishList[key]; let sub = subscribeList[key]; let arr = [...pub,...sub]; while(arr.length){ let item = arr.shift(); item(key); } }}class Employees { constructor(name){ this.name = name; } getName(){ let {name} = this; return name; } receivedMessage(key,name){ console.log(`${name}收到了${key}發(fā)來(lái)的消息`); }}class Public { constructor(name){ this.name = name; } getName(){ let {name} = this; return name; } sendMessage(key){ console.log(`${key}發(fā)送了一條消息`); }}let broker = new Broker();let SundayPublic = new Public('Sunday');let MayPublic = new Public('May');let Angie = new Employees('Angie');let Aaron = new Employees('Aaron');broker.Subscribe(() => { Angie.receivedMessage(SundayPublic.getName(),Angie.getName());},SundayPublic.getName());broker.Subscribe(() => { Angie.receivedMessage(SundayPublic.getName(),Aaron.getName());},SundayPublic.getName());broker.Subscribe(() => { Aaron.receivedMessage(MayPublic.getName(),Aaron.getName());},MayPublic.getName());broker.Release(MayPublic.sendMessage,MayPublic.getName());broker.Release(SundayPublic.sendMessage,SundayPublic.getName());broker.Run(SundayPublic.getName());broker.Run(MayPublic.getName());// Sunday發(fā)送了一條消息// Angie收到了Sunday發(fā)來(lái)的消息// Aaron收到了Sunday發(fā)來(lái)的消息// May發(fā)送了一條消息// Aaron收到了May發(fā)來(lái)的消息

通過(guò)上面的輸出結(jié)果可以得出,只要訂閱過(guò)該公眾號(hào)的用戶,只要公眾號(hào)發(fā)送一條消息,所有訂閱過(guò)該條消息的用戶都是可以收到這條消息。雖然代碼有點(diǎn)多,但是確確實(shí)實(shí)能夠體現(xiàn)發(fā)布訂閱模式的魅力,很不錯(cuò)。

優(yōu)點(diǎn) 支持簡(jiǎn)單的廣播通信,當(dāng)對(duì)象狀態(tài)發(fā)生改變時(shí),會(huì)自動(dòng)通知已經(jīng)訂閱過(guò)的對(duì)象。 發(fā)布者與訂閱者耦合性降低,發(fā)布者只管發(fā)布一條消息出去,它不關(guān)心這條消息如何被訂閱者使用,同時(shí),訂閱者只監(jiān)聽(tīng)發(fā)布者的事件名,只要發(fā)布者的事件名不變,它不管發(fā)布者如何改變;同理賣(mài)家(發(fā)布者)它只需要將鞋子來(lái)貨的這件事告訴訂閱者(買(mǎi)家),他不管買(mǎi)家到底買(mǎi)還是不買(mǎi),還是買(mǎi)其他賣(mài)家的。只要鞋子到貨了就通知訂閱者即可。缺點(diǎn) 創(chuàng)建訂閱者需要消耗一定的時(shí)間和內(nèi)存。 雖然可以弱化對(duì)象之間的聯(lián)系,如果過(guò)度使用的話,反而使代碼不好理解及代碼不好維護(hù)。小結(jié)

發(fā)布訂閱模式可以降低發(fā)布者與訂閱者之間的耦合程度,兩者之間從來(lái)不關(guān)系你是誰(shuí),你要作什么?訂閱者只需要跟隨發(fā)布者,若發(fā)布者發(fā)生變化就會(huì)通知訂閱者應(yīng)該也做出相對(duì)于的變化。發(fā)布者與訂閱者之間不存在直接通信,他們所有的一切事情都是通過(guò)中介者相互通信,它過(guò)濾所有傳入的消息并相應(yīng)地分發(fā)它們。發(fā)布訂閱模式可用于在不同系統(tǒng)組件之間傳遞消息的模式,而這些組件不知道關(guān)于彼此身份的任何信息。

觀察者模式與發(fā)布訂閱的區(qū)別 在Observer模式中,Observers知道Subject,同時(shí)Subject還保留了Observers的記錄。然而,在發(fā)布者/訂閱者中,發(fā)布者和訂閱者不需要彼此了解。他們只是在消息隊(duì)列或代理的幫助下進(jìn)行通信。 在Publisher / Subscriber模式中,組件是松散耦合的,而不是Observer模式。 觀察者模式主要以同步方式實(shí)現(xiàn),即當(dāng)某些事件發(fā)生時(shí),Subject調(diào)用其所有觀察者的適當(dāng)方法。發(fā)布者/訂閱者在大多情況下是異步方式(使用消息隊(duì)列)。 觀察者模式需要在單個(gè)應(yīng)用程序地址空間中實(shí)現(xiàn)。另一方面,發(fā)布者/訂閱者模式更像是跨應(yīng)用程序模式。

JavaScript設(shè)計(jì)模式之觀察者模式與發(fā)布訂閱模式詳解

如果以結(jié)構(gòu)來(lái)分辨模式,發(fā)布訂閱模式相比觀察者模式多了一個(gè)中間件訂閱器,所以發(fā)布訂閱模式是不同于觀察者模式的。如果以意圖來(lái)分辨模式,他們都是實(shí)現(xiàn)了對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都將得到通知,并自動(dòng)更新,那么他們就是同一種模式,發(fā)布訂閱模式是在觀察者模式的基礎(chǔ)上做的優(yōu)化升級(jí)。在觀察者模式中,觀察者需要直接訂閱目標(biāo)事件。在目標(biāo)發(fā)出內(nèi)容改變的事件后,直接接收事件并作出響應(yīng)。發(fā)布訂閱模式相比觀察者模式多了個(gè)事件通道,訂閱者和發(fā)布者不是直接關(guān)聯(lián)的。目標(biāo)和觀察者是直接聯(lián)系在一起的。觀察者把自身添加到了目標(biāo)對(duì)象中,可見(jiàn)和發(fā)布訂閱模式差別還是很大的。在這種模式下,目標(biāo)更像一個(gè)發(fā)布者,他讓添加進(jìn)來(lái)的所有觀察者都執(zhí)行了傳入的函數(shù),而觀察者就像一個(gè)訂閱者。雖然兩種模式都存在訂閱者和發(fā)布者(具體觀察者可認(rèn)為是訂閱者、具體目標(biāo)可認(rèn)為是發(fā)布者),但是觀察者模式是由具體目標(biāo)調(diào)度的,而發(fā)布/訂閱模式是統(tǒng)一由調(diào)度中心調(diào)的,所以觀察者模式的訂閱者與發(fā)布者之間是存在依賴的,而發(fā)布/訂閱模式則不會(huì)。

總結(jié)

雖然在學(xué)習(xí)這兩種模式的時(shí)候有很多的坎坷,最終還是按照自己的理解寫(xiě)出來(lái)了兩個(gè)案例。或許理解的有偏差,如果哪里有問(wèn)題,希望大家在下面留言指正,我會(huì)盡快做出修復(fù)的。

感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。

更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T(mén)教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》

希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
伊人成人在线视频| 久久久噜噜噜| 亚洲福利一区| 国产一区二区亚洲| 国产免费播放一区二区| 欧美视频二区| 日韩精品久久久久久| 丰满少妇一区| 国内精品伊人| 精品丝袜久久| 成人黄色av| 久久国产免费| 亚洲精品在线二区| 另类综合日韩欧美亚洲| 欧美日韩国产免费观看| 国产探花在线精品| 亚洲综合中文| 91九色精品| 欧美精品aa| 日韩欧美中文字幕在线视频| 日韩一级精品| а√天堂8资源中文在线| 久久精品理论片| 国产精品网在线观看| 久久尤物视频| 亚洲不卡系列| 久久先锋影音| 国产视频一区二| 日本美女一区| 99视频一区| 日韩不卡手机在线v区| 国产精品一区二区三区美女| 日产精品一区二区| 国产aa精品| 久久国产日本精品| 久久国产88| 国产亚洲人成a在线v网站| 国产美女久久| 国产美女高潮在线| 亚洲精品美女| 欧美好骚综合网| 91一区二区三区四区| 欧美精品观看| 快播电影网址老女人久久| 亚洲精品在线二区| 日韩专区精品| 美女被久久久| 肉色欧美久久久久久久免费看 | 国产不卡一区| 亚洲无线观看| av一区在线| 久久激情五月婷婷| 久久精品影视| 麻豆中文一区二区| 水野朝阳av一区二区三区| 国产欧美日韩精品一区二区免费| 亚洲伦乱视频| 国产极品一区| 日产欧产美韩系列久久99| 欧美一区激情| 亚洲高清久久| 国产美女高潮在线观看| 国产日韩在线观看视频| 老鸭窝毛片一区二区三区| 国产拍在线视频| 精品少妇av| 国产三级精品三级在线观看国产| 性色一区二区| 欧美中文字幕一区二区| 精品视频一区二区三区四区五区| 亚洲3区在线| 亚洲欧美网站在线观看| 亚洲深夜影院| 黄页网站一区| 日本久久综合| 精品免费av一区二区三区| 国产精品jk白丝蜜臀av小说| 日本欧美一区二区| 三级亚洲高清视频| 亚洲欧美网站| 婷婷五月色综合香五月| 日本成人手机在线| 男女性色大片免费观看一区二区| 伊人精品视频| 日韩精品高清不卡| 国产欧美精品| 色乱码一区二区三区网站| 国产aⅴ精品一区二区四区| 国产不卡人人| 日韩一区电影| 精品三级久久久| 日韩中文在线电影| 99久久精品网站| 国产高清一区二区| 日韩精品欧美成人高清一区二区| 国产精品激情| 久久久久美女| 鲁大师影院一区二区三区| 中文字幕成人| 国产精品一区高清| 91精品xxx在线观看| 午夜久久久久| 国产亚洲精aa在线看| 国产精品扒开腿做爽爽爽软件| 日韩精品一级| 麻豆一区二区三区| 国产视频欧美| 麻豆国产91在线播放| 久久国产亚洲| 97久久精品| 欧美成人基地 | 日韩精品三区四区| 国产精品**亚洲精品| 日韩欧美二区| 亚洲三级在线| 成人在线黄色| 日韩中文字幕亚洲一区二区va在线| 久久激情综合网| 欧美~级网站不卡| 日韩欧美中文字幕在线视频| 久久精品国内一区二区三区水蜜桃| 日韩精品一区第一页| 欧美国产美女| 国产欧美日本| 欧美日韩一区二区三区不卡视频| 国产精品一线| 日韩和欧美一区二区三区| 亚洲免费观看| 日韩专区欧美专区| 日本不卡在线视频| 亚洲欧美网站在线观看| 亚洲欧美日韩一区在线观看| 亚洲午夜一级| 免费久久精品| 好看不卡的中文字幕| 免费不卡中文字幕在线| 国产精品日韩久久久| 在线精品亚洲| 欧美日韩亚洲一区三区| 国产欧美激情| 亚洲精品**中文毛片| 亚洲福利国产| 亚洲精品第一| 免费看久久久| 成人啊v在线| 亚洲精品国产嫩草在线观看| 91精品国产自产在线观看永久∴| 亚洲人成亚洲精品| 国产亚洲精品美女久久| 久久超级碰碰| 日韩激情网站| 电影亚洲精品噜噜在线观看 | 国产色综合网| 国产日韩三级| 亚洲欧美日韩国产综合精品二区| 欧美激情aⅴ一区二区三区 | 日韩专区欧美专区| 天堂日韩电影| 精品视频久久| 神马午夜久久| av亚洲一区二区三区| 欧美精品一区二区三区精品| 夜久久久久久| 最新日韩av| 国产综合视频| 日韩中文首页| 精品亚洲成人| 蜜桃tv一区二区三区| 日韩在线黄色| 免费在线观看一区| 亚洲婷婷丁香| 成人国产精品一区二区网站| 日韩国产一区| 国产精品专区免费| 国产一区白浆| av中文字幕在线观看第一页 | 国产高清视频一区二区| 国产亚洲毛片| 国产精品亚洲四区在线观看 | 免费在线视频一区| 免费久久99精品国产| 国际精品欧美精品| 噜噜噜躁狠狠躁狠狠精品视频| 久久只有精品| 国产精品天堂蜜av在线播放| 日本va欧美va精品发布| 91精品福利| 亚洲二区视频| 国产精品对白久久久久粗| 丁香婷婷久久| 韩国女主播一区二区三区| а√天堂8资源在线| 伊人成人在线视频| 日韩和欧美一区二区| 视频在线不卡免费观看| 视频在线观看91| 日韩高清在线观看一区二区| 福利视频一区| 久久亚洲国产精品一区二区| 精品国产一区二区三区av片|