3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean

發布時間:2025/3/21 c/c++ 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ?十年前,Martin Fowler撰寫了GUI Architectures一文,至今被奉為經典。本文所談的所謂架構二字,核心即是對于富客戶端的代碼組織/職責劃分。縱覽這十年內的架構模式變遷,大概可以分為MV*與Unidirectional兩大類,而Clean Architecture則是以嚴格的層次劃分獨辟蹊徑。從筆者的認知來看,從MVC到MVP的變遷完成了對于View與Model的解耦合,改進了職責分配與可測試性。而從MVP到MVVM,添加了View與ViewModel之間的數據綁定,使得View完全的無狀態化。最后,整個從MV*到Unidirectional的變遷即是采用了消息隊列式的數據流驅動的架構,并且以Redux為代表的方案將原本MV*中碎片化的狀態管理變為了統一的狀態管理,保證了狀態的有序性與可回溯性。

筆者在撰寫本文的時候也不可避免的帶了很多自己的觀點,在漫長的GUI架構模式變遷過程中,很多概念其實是交錯復雜,典型的譬如MVP與MVVM的區別,筆者按照自己的理解強行定義了二者的區分邊界,不可避免的帶著自己的主觀想法。另外,鑒于筆者目前主要進行的是Web方面的開發,因此在整體傾向上是支持Unidirectional Architecture并且認為集中式的狀態管理是正確的方向。但是必須要強調,GUI架構本身是無法脫離其所依托的平臺,下文筆者也會淺述由于Android與iOS本身SDK API的特殊性,生搬硬套其他平臺的架構模式也是邯鄲學步,沐猴而冠。不過總結而言,它山之石,可以攻玉,本身我們所處的開發環境一直在不斷變化,對于過去的精華自當應該保留,并且與新的環境相互印證,觸類旁通。

Introduction

Make everything as simple as possible, but not simpler?—?Albert Einstein

Graphical User Interfaces一直是軟件開發領域的重要組成部分,從當年的MFC,到WinForm/Java Swing,再到WebAPP/Android/iOS引領的智能設備潮流,以及未來可能的AR/VR,GUI應用開發中所面臨的問題一直在不斷演變,但是從各種具體問題中抽象而出的可以復用的模式恒久存在。而這些模式也就是所謂應用架構的核心與基礎。對于所謂應用架構,空談誤事,不談誤己,筆者相信不僅僅只有自己想把那一團糟的代碼給徹底拋棄。往往對于架構的認知需要一定的大局觀與格局眼光,每個有一定經驗的客戶端程序開發者,無論是Web、iOS還是Android,都會有自己熟悉的開發流程習慣,但是筆者認為架構認知更多的是道,而非術。當你能夠以一種指導思想在不同的平臺上能夠進行高效地開發時,你才能真正理解架構。這個有點像張三豐學武,心中無招,方才達成。筆者這么說只是為了強調,盡量地可以不拘泥于某個平臺的具體實現去審視GUI應用程序架構模式,會讓你有不一樣的體驗。譬如下面這個組裝Android機器人的圖:

怎么去焊接兩個組件,屬于具體的術實現,而應該焊接哪兩個組件就是術,作為合格的架構師總不能把腳和頭直接焊接在一起,而忽略中間的連接模塊。對于軟件開發中任何一個方面,我們都希望能夠尋找到一個抽象程度適中,能夠在接下來的4,5年內正常運行與方便維護擴展的開發模式。引申下筆者在我的編程之路中的論述,目前在GUI架構模式中,無論是Android、iOS還是Web,都在經歷著從命令式編程到聲明式/響應式編程,從Passive Components到Reactive Components,從以元素操作為核心到以數據流驅動為核心的變遷(關于這幾句話的解釋可以參閱下文的Declarative vs. Imperative這一小節)。

Terminology:名詞解釋

正文之前,我們先對一些概念進行闡述:

  • User Events/用戶事件:即是來自于可輸入設備上的用戶操作產生的數據,譬如鼠標點擊、滾動、鍵盤輸入、觸摸等等。

  • User Interface Rendering/用戶界面渲染:View這個名詞在前后端開發中都被廣泛使用,為了明晰該詞的含義,我們在這里使用用戶渲染這個概念,來描述View,即是以HTML或者JSX或者XAML等等方式在屏幕上產生的圖形化輸出內容。

  • UI Application:允許接收用戶輸入,并且將輸出渲染到屏幕上的應用程序,該程序能夠長期運行而不只是渲染一次即結束

Passive Module & Reactive Module

箭頭表示的歸屬權實際上也是Passive Programming與Reactive Programming的區別,譬如我們的系統中有Foo與Bar兩個模塊,可以把它們當做OOP中的兩個類。如果我們在Foo與Bar之間建立一個箭頭,也就意味著Foo能夠影響Bar中的狀態:

譬如Foo在進行一次網絡請求之后將Bar內部的計數器加一操作:

// This is inside the Foo modulefunction onNetworkRequest() {// ...Bar.incrementCounter();// ... }

在這里將這種邏輯關系可以描述為Foo擁有著網絡請求完成之后將Bar內的計數器加一這個關系的控制權,也就是Foo占有主導性,而Bar相對而言是Passive被動的:

Bar是Passive的,它允許其他模塊改變其內部狀態。而Foo是主動地,它需要保證能夠正確地更新Bar的內部狀態,Passive模塊并不知道誰會更新到它。而另一種方案就是類似于控制反轉,由Bar完成對于自己內部狀態的更新:

在這種模式下,Bar監聽來自于Foo中的事件,并且在某些事件發生之后進行內部狀態更新:

// This is inside the Bar moduleFoo.addOnNetworkRequestListener(() => {self.incrementCounter(); // self is Bar});

此時Bar就變成了Reactive Module,它負責自己的內部的狀態更新以響應外部的事件,而Foo并不知道它發出的事件會被誰監聽。

Declarative vs. Imperative:命令式編程與聲明式編程

three-ds-of-web-development

前端攻略-從路人甲到英雄無敵二:JavaScript 與不斷演化的框架

形象地來描述命令式編程與聲明式編程的區別,就好像C#/JavaScript與類似于XML或者HTML這樣的標記語言之間的區別。命令式編程關注于how to do what you want done,即事必躬親,需要安排好每個要做的細節。而聲明式編程關注于what you want done without worrying about how,即只需要聲明要做的事情而不用將具體的過程再耦合進來。對于開發者而言,聲明式編程將很多底層的實現細節向開發者隱藏,而使得開發者可以專注于具體的業務邏輯,同時也保證了代碼的解耦與單一職責。譬如在Web開發中,如果你要基于jQuery將數據填充到頁面上,那么大概按照命令式編程的模式你需要這么做:

var options = $("#options"); $.each(result, function() {options.append($("<option />").val(this.id).text(this.name)); });

而以Angular 1聲明式的方式進行編寫,那么是如下的標記模樣:

<div ng-repeat="item in items" ng-click="select(item)">{{item.name}} </div>

而在iOS和Android開發中,近年來函數響應式編程(Functional Reactive Programming)也非常流行,參閱筆者關于響應式編程的介紹可以了解,響應式編程本身是基于流的方式對于異步操作的一種編程優化,其在整個應用架構的角度看更多的是細節點的優化。以RxSwift為例,通過響應式編程可以編寫出非常優雅的用戶交互代碼:

let searchResults = searchBar.rx_text.throttle(0.3, scheduler: MainScheduler.instance).distinctUntilChanged().flatMapLatest { query -> Observable<[Repository]> inif query.isEmpty {return Observable.just([])}return searchGitHub(query).catchErrorJustReturn([])}.observeOn(MainScheduler.instance) searchResults.bindTo(tableView.rx_itemsWithCellIdentifier("Cell")) {(index, repository: Repository, cell) incell.textLabel?.text = repository.namecell.detailTextLabel?.text = repository.url}.addDisposableTo(disposeBag)

其直觀的效果大概如下圖所示:

到這里可以看出,無論是從命令式編程與聲明式編程的對比還是響應式編程的使用,我們開發時的關注點都慢慢轉向了所謂的數據流。便如MVVM,雖然它還是雙向數據流,但是其使用的Data-Binding也意味著開發人員不需要再去以命令地方式尋找元素,而更多地關注于應該給綁定的對象賦予何值,這也是數據流驅動的一個重要體現。而Unidirectional Architecture采用了類似于Event Source的方式,更是徹底地將組件之間、組件與功能模塊之間的關聯交于數據流操控。

談到架構,我們關心哪些方面?

當我們談論所謂客戶端開發的時候,我們首先會想到怎么保證向后兼容、怎么使用本地存儲、怎么調用遠程接口、如何有效地利用內存/帶寬/CPU等資源,不過最核心的還是怎么繪制界面并且與用戶進行交互,關于這部分詳細的知識點綱要推薦參考筆者的我的編程之路——知識管理與知識體系這篇文章或者這張知識點列表思維腦圖。

而當我們提綱挈領、高屋建瓴地以一個較高的抽象的視角來審視總結這個知識點的時候會發現,我們希望的好的架構,便如在引言中所說,即是有好的代碼組織方式/合理的職責劃分粒度。筆者腦中會出現如下這樣的一個層次結構,可以看出,最核心的即為View與ViewLogic這兩部分:

實際上,對于富客戶端的代碼組織/職責劃分,從具體的代碼分割的角度,即是功能的模塊化界面的組件化狀態管理這三個方面。最終呈獻給用戶的界面,筆者認為可以抽象為如下等式:View = f(State,Template)。而ViewLogic中對于類/模塊之間的依賴關系,即屬于代碼組織,譬如MVC中的View與Controller之間的從屬關系。而對于動態數據,即所謂應用數據的管理,屬于狀態管理這一部分,譬如APP從后來獲取了一系列的數據,如何將這些數據渲染到用戶界面上使得用戶可見,這樣的不同部分之間的協同關系、整個數據流的流動,即屬于狀態管理。

分久必合,合久必分

實際上從MVC、MVP到MVVM,一直圍繞的核心問題就是如何分割ViewLogic與View,即如何將負責界面展示的代碼與負責業務邏輯的代碼進行分割。所謂分久必合,合久必分,從筆者自我審視的角度,發現很有趣的一點。Android與iOS中都是從早期的用代碼進行組件添加與布局到專門的XML/Nib/StoryBoard文件進行布局,Android中的Annotation/DataBinding、iOS中的IBOutlet更加地保證了View與ViewLogic的分割(這一點也是從元素操作到以數據流驅動的變遷,我們不需要再去編寫大量的findViewById)。而Web的趨勢正好有點相反,無論是WebComponent還是ReactiveComponent都是將ViewLogic與View置于一起,特別是JSX的語法將JavaScript與HTML混搭,很像當年的PHP/JSP與HTML混搭。這一點也是由筆者在上文提及的Android/iOS本身封裝程度較高的、規范的API決定的。對于Android/iOS與Web之間開發體驗的差異,筆者感覺很類似于靜態類型語言與動態類型語言之間的差異。

功能的模塊化

老實說在AMD/CMD規范之前,或者說在ES6的模塊引入與Webpack的模塊打包出來之前,功能的模塊化依賴一直也是個很頭疼的問題。

SOLID中的接口隔離原則,大量的IOC或者DI工具可以幫我們完成這一點,就好像Spring中的@Autowire或者Angular 1中的@Injection,都給筆者很好地代碼體驗。

在這里筆者首先要強調下,從代碼組織的角度來看,項目的構建工具與依賴管理工具會深刻地影響到代碼組織,這一點在功能的模塊化中尤其顯著。譬如筆者對于Android/Java構建工具的使用變遷經歷了從Eclipse到Maven再到Gradle,筆者會將不同功能邏輯的代碼封裝到不同的相對獨立的子項目中,這樣就保證了子項目與主項目之間的一定隔離,方便了測試與代碼維護。同樣的,在Web開發中從AMD/CMD規范到標準的ES6模塊與Webpack編譯打包,也使得代碼能夠按照功能盡可能地解耦分割與避免冗余編碼。而另一方面,依賴管理工具也極大地方便我們使用第三方的代碼與發布自定義的依賴項,譬如Web中的NPM與Bower,iOS中的CocoaPods都是十分優秀的依賴發布與管理工具,使我們不需要去關心第三方依賴的具體實現細節即能夠透明地引入使用。因此選擇合適的項目構建工具與依賴管理工具也是好的GUI架構模式的重要因素之一。不過從應用程序架構的角度看,無論我們使用怎樣的構建工具,都可以實現或者遵循某種架構模式,筆者認為二者之間也并沒有必然的因果關系。

界面的組件化

A component is a small piece of the user interface of our application, a view, that can be composed with other components to make more advanced components.

何謂組件?一個組件即是應用中用戶交互界面的部分組成,組件可以通過組合封裝成更高級的組件。組件可以被放入層次化的結構中,即可以是其他組件的父組件也可以是其他組件的子組件。根據上述的組件定義,筆者認為像Activity或者UIViewController都不能算是組件,而像ListView或者UITableView可以看做典型的組件。

我們強調的是界面組件的Composable&Reusable,即可組合性與可重用性。當我們一開始接觸到Android或者iOS時,因為本身SDK的完善度與規范度較高,我們能夠很多使用封裝程度較高的組件。譬如ListView,無論是Android中的RecycleView還是iOS中的UITableView或者UICollectionView,都為我們提供了。凡事都有雙面性,這種較高程度的封裝與規范統一的API方便了我們的開發,但是也限制了我們自定義的能力。同樣的,因為SDK的限制,真正意義上可復用/組合的組件也是不多,譬如你不能將兩個ListView再組合成一個新的ListView。在React中有所謂的controller-view的概念,即意味著某個React組件同時擔負起MVC中Controller與View的責任,也就是JSX這種將負責ViewLogic的JavaScript代碼與負責模板的HTML混編的方式。

界面的組件化還包括一個重要的點就是路由,譬如Android中的AndRouter、iOS中的JLRoutes都是集中式路由的解決方案,不過集中式路由在Android或者iOS中并沒有大規模推廣。iOS中的StoryBoard倒是類似于一種集中式路由的方案,不過更偏向于以UI設計為核心。筆者認為這一點可能是因為Android或者iOS本身所有的代碼都是存放于客戶端本身,而Web中較傳統的多頁應用方式還需要用戶跳轉頁面重新加載,而后在單頁流行之后即不存在頁面級別的跳轉,因此在Web單頁應用中集中式路由較為流行而Android、iOS中反而不流行。

無狀態的組件

無狀態的組件的構建函數是純函數(pure function)并且引用透明的(refferentially transparent),在相同輸入的情況下一定會產生相同的組件輸出,即符合View = f(State,Template)公式。筆者覺得Android中的ListView/RecycleView,或者iOS中的UITableView,也是無狀態組件的典型。譬如在Android中,可以通過動態設置Adapter實例來為RecycleView進行源數據的設置,而作為View層以IoC的方式與具體的數據邏輯解耦。

組件的可組合性與可重用性往往最大的阻礙就是狀態,一般來說,我們希望能夠重用或者組合的組件都是

Generalization,而狀態往往是Specification,即領域特定的。同時,狀態也會使得代碼的可讀性與可測試性降低,在有狀態的組件中,我們并不能通過簡單地閱讀代碼就知道其功能。如果借用函數式編程的概念,就是因為副作用的引入使得函數每次回產生不同的結果。函數式編程中存在著所謂Pure Function,即純函數的概念,函數的返回值永遠只受到輸入參數的影響。譬如(x)=>x*2這個函數,輸入的x值永遠不會被改變,并且返回值只是依賴于輸入的參數。而Web開發中我們也經常會處于帶有狀態與副作用的環境,典型的就是Browser中的DOM,之前在jQuery時代我們會經常將一些數據信息緩存在DOM樹上,也是典型的將狀態與模板混合的用法。這就導致了我們并不能控制到底應該何時去進行重新渲染以及哪些狀態變更的操作才是必須的,

var Header = component(function (data) {// First argument is h1 metadatareturn h1(null, data.text); });// Render the component to our DOM render(Header({text: 'Hello'}), document.body);// Some time later, we change it, by calling the // component once more. setTimeout(function () {render(Header({text: 'Changed'}), document.body); }, 1000); var hello = Header({ text: 'Hello' }); var bye = Header({ text: 'Good Bye' });

狀態管理

可變的與不可預測的狀態是軟件開發中的萬惡之源

  • Web開發中所謂狀態淺析:Domain State&UI State

上文提及,我們盡可能地希望組件的無狀態性,那么整個應用中的狀態管理應該盡量地放置在所謂High-Order Component或者Smart Component中。在React以及Flux的概念流行之后,Stateless Component的概念深入人心,不過其實對于MVVM中的View,也是無狀態的View。通過雙向數據綁定將界面上的某個元素與ViewModel中的變量相關聯,筆者認為很類似于HOC模式中的Container與Component之間的關聯。隨著應用的界面與功能的擴展,狀態管理會變得愈發混亂。這一點,無論前后端都有異曲同工之難,筆者在基于Redux思想與RxJava的SpringMVC中Controller的代碼風格實踐一文中對于服務端應用程序開發中的狀態管理有過些許討論。

Features of Good Architectural Pattern:何為好的架構模式

Balanced Distribution of Responsibilities:合理的職責劃分

合理的職責劃分即是保證系統中的不同組件能夠被分配合理的職責,也就是在復雜度之間達成一個平衡,職責劃分最權威的原則就是所謂Single Responsibility Principle,單一職責原則。

Testability:可測試性

可測試性是保證軟件工程質量的重要手段之一,也是保證產品可用性的重要途徑。在傳統的GUI程序開發中,特別是對于界面的測試常常設置于狀態或者運行環境,并且很多與用戶交互相關的測試很難進行場景重現,或者需要大量的人工操作去模擬真實環境。

Ease of Use:易用性

代碼的易用性保證了程序架構的簡潔與可維護性,所謂最好的代碼就是永遠不需要重寫的代碼,而程序開發中盡量避免的代碼復用方法就是復制粘貼。

Fractal:碎片化,易于封裝與分發

In fractal architectures, the whole can be naively packaged as a component to be used in some larger application.In non-fractal architectures, the non-repeatable parts are said to be orchestrators over the parts that have hierarchical composition.

  • By André Staltz

所謂的Fractal Architectures,即你的應用整體都可以像單個組件一樣可以方便地進行打包然后應用到其他項目中。而在Non-Fractal Architectures中,不可以被重復使用的部分被稱為層次化組合中的Orchestrators。譬如你在Web中編寫了一個登錄表單,其中的布局、樣式等部分可以被直接復用,而提交表單這個操作,因為具有應用特定性,因此需要在不同的應用中具有不同的實現。譬如下面有一個簡單的表單:

<form action="form_action.asp" method="get"><p>First name: <input type="text" name="fname" /></p><p>Last name: <input type="text" name="lname" /></p><input type="submit" value="Submit" /> </form>

因為不同的應用中,form的提交地址可能不一致,那么整個form組件是不可直接重用的,即Non-Fractal Architectures。而form中的input組件是可以進行直接復用的,如果將input看做一個單獨的GUI架構,即是所謂的Fractal Architectures,form就是所謂的Orchestrators,將可重用的組件編排組合,并且設置應用特定的一些信息。

Reference

Overview

  • Martin Fowler-GUI Architectures

  • Comparison-of-Architecture-presentation-patterns

MV*

  • THE EVOLUTION OF ANDROID ARCHITECTURE

  • the-evolution-of-android-architecture

  • android-architecture

  • ios-architecture-patterns

  • Albert Zuurbier:MVC VS. MVP VS. MVVM

MVC

  • Model-View-Controller (MVC) in iOS: A Modern Approach

  • 為什么我不再使用MVC框架

  • difference-between-mvc-mvp-mvvm-swapneel-salunkhe

MVP

  • presentation-model-and-passive-view-in-mvp-the-android-way

  • Repository that showcases 3 Android app architectures

MVVM

  • approaching-android-with-mvvm

Unidirectional Architecture

  • unidirectional-user-interface-architectures

  • [Facebook: MVC Does Not Scale, Use Flux Instead [Updated]](https://www.infoq.com/news/20...

  • mvvm-mvc-is-dead-is-unidirectional-a-mvvm-mvc-killer

  • flux-vs-mvc-design-patterns

  • jedux:Redux architecture for Android

  • writing-a-todo-app-with-redux-on-android

  • state-streams-and-react

Viper/Clean Architecture

  • Uncle Bob:the-clean-architecture

  • Android Clean Architecture

  • A sample iOS app built using the Clean Swift architecture

  • Introduction to VIPER

MV*:Fragmentary State 碎片化的狀態與雙向數據流

MVC模式將有關于渲染、控制與數據存儲的概念有機分割,是GUI應用架構模式的一個巨大成就。但是,MVC模式在構建能夠長期運行、維護、有效擴展的應用程序時遇到了極大的問題。MVC模式在一些小型項目或者簡單的界面上仍舊有極大的可用性,但是在現代富客戶端開發中導致職責分割不明確、功能模塊重用性、View的組合性較差。作為繼任者MVP模式分割了View與Model之間的直接關聯,MVP模式中也將更多的ViewLogic轉移到Presenter中進行實現,從而保證了View的可測試性。而最年輕的MVVM將ViewLogic與View剝離開來,保證了View的無狀態性、可重用性、可組合性以及可測試性。總結而言,MV*模型都包含了以下幾個方面:

  • Models:負責存儲領域/業務邏輯相關的數據與構建數據訪問層,典型的就是譬如Person、PersonDataProvider。

  • Views:負責將數據渲染展示給用戶,并且響應用戶輸入

  • Controller/Presenter/ViewModel:往往作為Model與View之間的中間人出現,接收View傳來的用戶事件并且傳遞給Model,同時利用從Model傳來的最新模型控制更新View

MVC:Monolithic Controller

相信每一個程序猿都會宣稱自己掌握MVC,這個概念淺顯易懂,并且貫穿了從GUI應用到服務端應用程序。MVC的概念源自Gamma, Helm, Johnson 以及Vlissidis這四人幫在討論設計模式中的Observer模式時的想法,不過在那本經典的設計模式中并沒有顯式地提出這個概念。我們通常認為的MVC名詞的正式提出是在1979年5月Trygve Reenskaug發表的Thing-Model-View-Editor這篇論文,這篇論文雖然并沒有提及Controller,但是Editor已經是一個很接近的概念。大概7個月之后,Trygve Reenskaug在他的文章Models-Views-Controllers中正式提出了MVC這個三元組。上面兩篇論文中對于Model的定義都非常清晰,Model代表著an abstraction in the form of data in a computing system.,即為計算系統中數據的抽象表述,而View代表著capable of showing one or more pictorial representations of the Model on screen and on hardcopy.,即能夠將模型中的數據以某種方式表現在屏幕上的組件。而Editor被定義為某個用戶與多個View之間的交互接口,在后一篇文章中Controller則被定義為了a special controller ... that permits the user to modify the information that is presented by the view.,即主要負責對模型進行修改并且最終呈現在界面上。從我的個人理解來看,Controller負責控制整個界面,而Editor只負責界面中的某個部分。Controller協調菜單、面板以及像鼠標點擊、移動、手勢等等很多的不同功能的模塊,而Editor更多的只是負責某個特定的任務。后來,Martin Fowler在2003開始編寫的著作Patterns of Enterprise Application Architecture中重申了MVC的意義:Model View Controller (MVC) is one of the most quoted (and most misquoted) patterns around.,將Controller的功能正式定義為:響應用戶操作,控制模型進行相應更新,并且操作頁面進行合適的重渲染。這是非常經典、狹義的MVC定義,后來在iOS以及其他很多領域實際上運用的MVC都已經被擴展或者賦予了新的功能,不過筆者為了區分架構演化之間的區別,在本文中僅會以這種最樸素的定義方式來描述MVC。

根據上述定義,我們可以看到MVC模式中典型的用戶場景為:

  • 用戶交互輸入了某些內容

  • Controller將用戶輸入轉化為Model所需要進行的更改

  • Model中的更改結束之后,Controller通知View進行更新以表現出當前Model的狀態

根據上述流程,我們可知經典的MVC模式的特性為:

  • View、Controller、Model中皆有ViewLogic的部分實現

  • Controller負責控制View與Model,需要了解View與Model的細節。

  • View需要了解Controller與Model的細節,需要在偵測用戶行為之后調用Controller,并且在收到通知后調用Model以獲取最新數據

  • Model并不需要了解Controller與View的細節,相對獨立的模塊

Observer Pattern:自帶觀察者模式的MVC

上文中也已提及,MVC濫觴于Observer模式,經典的MVC模式也可以與Observer模式相結合,其典型的用戶流程為:

  • 用戶交互輸入了某些內容

  • Controller將用戶輸入轉化為Model所需要進行的更改

  • View作為Observer會監聽Model中的任意更新,一旦有更新事件發出,View會自動觸發更新以展示最新的Model狀態

可知其與經典的MVC模式區別在于不需要Controller通知View進行更新,而是由Model主動調用View進行更新。這種改變提升了整體效率,簡化了Controller的功能,不過也導致了View與Model之間的緊耦合。

MVP:Decoupling View and Model 將視圖與模型解耦, View<->Presenter

維基百科將MVP稱為MVC的一個推導擴展,觀其淵源而知其所以然。對于MVP概念的定義,Microsoft較為明晰,而Martin Fowler的定義最為廣泛接受。MVP模式在WinForm系列以Visual-XXX命名的編程語言與Java Swing等系列應用中最早流傳開來,不過后來ASP.NET以及JFaces也廣泛地使用了該模式。在MVP中用戶不再與Presenter進行直接交互,而是由View完全接管了用戶交互,譬如窗口上的每個控件都知道如何響應用戶輸入并且合適地渲染來自于Model的數據。而所有的事件會被傳輸給Presenter,Presenter在這里就是View與Model之間的中間人,負責控制Model進行修改以及將最新的Model狀態傳遞給View。這里描述的就是典型的所謂Passive View版本的MVP,其典型的用戶場景為:

  • 用戶交互輸入了某些內容

  • View將用戶輸入轉化為發送給Presenter

  • Presenter控制Model接收需要改變的點

  • Model將更新之后的值返回給Presenter

  • Presenter將更新之后的模型返回給View

根據上述流程,我們可知Passive View版本的MVP模式的特性為:

  • View、Presenter、Model中皆有ViewLogic的部分實現

  • Presenter負責連接View與Model,需要了解View與Model的細節。

  • View需要了解Presenter的細節,將用戶輸入轉化為事件傳遞給Presenter

  • Model需要了解Presenter的細節,在完成更新之后將最新的模型傳遞給Presenter

  • View與Model之間相互解耦合

Supervising Controller MVP

簡化Presenter的部分功能,使得Presenter只起到需要復雜控制或者調解的操作,而簡單的Model展示轉化直接由View與Model進行交互:

MVVM:Data Binding & Stateless View 數據綁定與無狀態的View,View<->ViewModels

Model View View-Model模型是MV*家族中最年輕的一位,也是由Microsoft提出,并經由Martin Fowler布道傳播。MVVM源于Martin Fowler的Presentation Model,Presentation Model的核心在于接管了View所有的行為響應,View的所有響應與狀態都定義在了Presentation Model中。也就是說,View不會包含任意的狀態。舉個典型的使用場景,當用戶點擊某個按鈕之后,狀態信息是從Presentation Model傳遞給Model,而不是從View傳遞給Presentation Model。任何控制組件間的邏輯操作,即上文所述的ViewLogic,都應該放置在Presentation Model中進行處理,而不是在View層,這一點也是MVP模式與Presentation Model最大的區別。

MVVM模式進一步深化了Presentation Model的思想,利用Data Binding等技術保證了View中不會存儲任何的狀態或者邏輯操作。在WPF中,UI主要是利用XAML或者XML創建,而這些標記類型的語言是無法存儲任何狀態的,就像HTML一樣(因此JSX語法其實是將View又有狀態化了),只是允許UI與某個ViewModel中的類建立映射關系。渲染引擎根據XAML中的聲明以及來自于ViewModel的數據最終生成呈現的頁面。因為數據綁定的特性,有時候MVVM也會被稱作MVB:Model View Binder。總結一下,MVVM利用數據綁定徹底完成了從命令式編程到聲明式編程的轉化,使得View逐步無狀態化。一個典型的MVVM的使用場景為:

  • 用戶交互輸入

  • View將數據直接傳送給ViewModel,ViewModel保存這些狀態數據

  • 在有需要的情況下,ViewModel會將數據傳送給Model

  • Model在更新完成之后通知ViewModel

  • ViewModel從Model中獲取最新的模型,并且更新自己的數據狀態

  • View根據最新的ViewModel的數據進行重新渲染

根據上述流程,我們可知MVVM模式的特性為:

  • ViewModel、Model中存在ViewLogic實現,View則不保存任何狀態信息

  • View不需要了解ViewModel的實現細節,但是會聲明自己所需要的數據類型,并且能夠知道如何重新渲染

  • ViewModel不需要了解View的實現細節(非命令式編程),但是需要根據View聲明的數據類型傳入對應的數據。ViewModel需要了解Model的實現細節。

  • Model不需要了解View的實現細節,需要了解ViewModel的實現細節

MV* in iOS

MVC

Cocoa MVC中往往會將大量的邏輯代碼放入ViewController中,這就導致了所謂的Massive ViewController,而且很多的邏輯操作都嵌入到了View的生命周期中,很難剝離開來。或許你可以將一些業務邏輯或者數據轉換之類的事情放到Model中完成,不過對于View而言絕大部分時間僅起到發送Action給Controller的作用。ViewController逐漸變成了幾乎所有其他組件的Delegate與DataSource,還經常會負責派發或者取消網絡請求等等職責。你的代碼大概是這樣的:

var userCell = tableView.dequeueReusableCellWithIdentifier("identifier") as UserCelluserCell.configureWithUser(user)

上面這種寫法直接將View于Model關聯起來,其實算是打破了Cocoa MVC的規范的,不過這樣也是能夠減少些Controller中的中轉代碼呢。這樣一個架構模式在進行單元測試的時候就顯得麻煩了,因為你的ViewController與View緊密關聯,使得其很難去進行測試,因為你必須為每一個View創建Mock對象并且管理其生命周期。另外因為整個代碼都混雜在一起,即破壞了職責分離原則,導致了系統的可變性與可維護性也很差。經典的MVC的示例程序如下:

import UIKitstruct Person { // Modellet firstName: Stringlet lastName: String}class GreetingViewController : UIViewController { // View + Controllervar person: Person!let showGreetingButton = UIButton()let greetingLabel = UILabel()override func viewDidLoad() {super.viewDidLoad()self.showGreetingButton.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)}func didTapButton(button: UIButton) {let greeting = "Hello" + " " + self.person.firstName + " " + self.person.lastNameself.greetingLabel.text = greeting}// layout code goes here}// Assembling of MVClet model = Person(firstName: "David", lastName: "Blaine")let view = GreetingViewController()view.person = model;

上面這種代碼一看就很難測試,我們可以將生成greeting的代碼移到GreetingModel這個單獨的類中,從而進行單獨的測試。不過我們還是很難去在GreetingViewController中測試顯示邏輯而不調用UIView相關的譬如viewDidLoad、didTapButton等等較為費時的操作。再按照我們上文提及的優秀的架構的幾個方面來看:

  • Distribution:View與Model是分割開來了,不過View與Controller是緊耦合的

  • Testability:因為較差的職責分割導致貌似只有Model部分方便測試

  • 易用性:因為程序比較直觀,可能容易理解。

MVP

Cocoa中MVP模式是將ViewController當做純粹的View進行處理,而將很多的ViewLogic與模型操作移動到Presenter中進行,代碼如下:

import UIKitstruct Person { // Modellet firstName: Stringlet lastName: String}protocol GreetingView: class {func setGreeting(greeting: String)}protocol GreetingViewPresenter {init(view: GreetingView, person: Person)func showGreeting()}class GreetingPresenter : GreetingViewPresenter {unowned let view: GreetingViewlet person: Personrequired init(view: GreetingView, person: Person) {self.view = viewself.person = person}func showGreeting() {let greeting = "Hello" + " " + self.person.firstName + " " + self.person.lastNameself.view.setGreeting(greeting)}}class GreetingViewController : UIViewController, GreetingView {var presenter: GreetingViewPresenter!let showGreetingButton = UIButton()let greetingLabel = UILabel()override func viewDidLoad() {super.viewDidLoad()self.showGreetingButton.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)}func didTapButton(button: UIButton) {self.presenter.showGreeting()}func setGreeting(greeting: String) {self.greetingLabel.text = greeting}// layout code goes here}// Assembling of MVPlet model = Person(firstName: "David", lastName: "Blaine")let view = GreetingViewController()let presenter = GreetingPresenter(view: view, person: model)view.presenter = presenter
  • Distribution:主要的業務邏輯分割在了Presenter與Model中,View相對呆板一點

  • Testability:較為方便地測試

  • 易用性:代碼職責分割的更為明顯,不過不像MVC那樣直觀易懂了

MVVM

import UIKitstruct Person { // Modellet firstName: Stringlet lastName: String}protocol GreetingViewModelProtocol: class {var greeting: String? { get }var greetingDidChange: ((GreetingViewModelProtocol) -> ())? { get set } // function to call when greeting did changeinit(person: Person)func showGreeting()}class GreetingViewModel : GreetingViewModelProtocol {let person: Personvar greeting: String? {didSet {self.greetingDidChange?(self)}}var greetingDidChange: ((GreetingViewModelProtocol) -> ())?required init(person: Person) {self.person = person}func showGreeting() {self.greeting = "Hello" + " " + self.person.firstName + " " + self.person.lastName}}class GreetingViewController : UIViewController {var viewModel: GreetingViewModelProtocol! {didSet {self.viewModel.greetingDidChange = { [unowned self] viewModel inself.greetingLabel.text = viewModel.greeting}}}let showGreetingButton = UIButton()let greetingLabel = UILabel()override func viewDidLoad() {super.viewDidLoad()self.showGreetingButton.addTarget(self.viewModel, action: "showGreeting", forControlEvents: .TouchUpInside)}// layout code goes here}// Assembling of MVVMlet model = Person(firstName: "David", lastName: "Blaine")let viewModel = GreetingViewModel(person: model)let view = GreetingViewController()view.viewModel = viewModel
  • Distribution:在Cocoa MVVM中,View相對于MVP中的View擔負了更多的功能,譬如需要構建數據綁定等等

  • Testability:ViewModel擁有View中的所有數據結構,因此很容易就可以進行測試

  • 易用性:相對而言有很多的冗余代碼

MV* in Android

此部分完整代碼在這里,筆者在這里節選出部分代碼方便對照演示。Android中的Activity的功能很類似于iOS中的UIViewController,都可以看做MVC中的Controller。在2010年左右經典的Android程序大概是這樣的:

TextView mCounterText;Button mCounterIncrementButton;int mClicks = 0;public void onCreate(Bundle b) {super.onCreate(b);mCounterText = (TextView) findViewById(R.id.tv_clicks);mCounterIncrementButton = (Button) findViewById(R.id.btn_increment);mCounterIncrementButton.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {mClicks++;mCounterText.setText(""+mClicks);}});}

后來2013年左右出現了ButterKnife這樣的基于注解的控件綁定框架,此時的代碼看上去是這樣的:

@Bind(R.id.tv_clicks) mCounterText;@OnClick(R.id.btn_increment)public void onSubmitClicked(View v) {mClicks++;mCounterText.setText("" + mClicks);}

后來Google官方也推出了數據綁定的框架,從此MVVM模式在Android中也愈發流行:

<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variable name="counter" type="com.example.Counter"/><variable name="counter" type="com.example.ClickHandler"/></data><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{counter.value}"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{handlers.clickHandle}"/></LinearLayout></layout>

后來Anvil這樣的受React啟發的組件式框架以及Jedux這樣借鑒了Redux全局狀態管理的框架也將Unidirectional 架構引入了Android開發的世界。

MVC

  • 聲明View中的組件對象或者Model對象

private Subscription subscription;private RecyclerView reposRecycleView;private Toolbar toolbar;private EditText editTextUsername;private ProgressBar progressBar;private TextView infoTextView;private ImageButton searchButton;
  • 將組件與Activity中對象綁定,并且聲明用戶響應處理函數

super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);progressBar = (ProgressBar) findViewById(R.id.progress);infoTextView = (TextView) findViewById(R.id.text_info);//Set up ToolBartoolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar);//Set up RecyclerViewreposRecycleView = (RecyclerView) findViewById(R.id.repos_recycler_view);setupRecyclerView(reposRecycleView);// Set up search buttonsearchButton = (ImageButton) findViewById(R.id.button_search);searchButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {loadGithubRepos(editTextUsername.getText().toString());}});//Set up username EditTexteditTextUsername = (EditText) findViewById(R.id.edit_text_username);editTextUsername.addTextChangedListener(mHideShowButtonTextWatcher);editTextUsername.setOnEditorActionListener(new TextView.OnEditorActionListener() {@Overridepublic boolean onEditorAction(TextView v, int actionId, KeyEvent event) {if (actionId == EditorInfo.IME_ACTION_SEARCH) {String username = editTextUsername.getText().toString();if (username.length() > 0) loadGithubRepos(username);return true;}return false;}});
  • 用戶輸入之后的更新流程

progressBar.setVisibility(View.VISIBLE);reposRecycleView.setVisibility(View.GONE);infoTextView.setVisibility(View.GONE);ArchiApplication application = ArchiApplication.get(this);GithubService githubService = application.getGithubService();subscription = githubService.publicRepositories(username).observeOn(AndroidSchedulers.mainThread()).subscribeOn(application.defaultSubscribeScheduler()).subscribe(new Subscriber<List<Repository>>() {@Overridepublic void onCompleted() {progressBar.setVisibility(View.GONE);if (reposRecycleView.getAdapter().getItemCount() > 0) {reposRecycleView.requestFocus();hideSoftKeyboard();reposRecycleView.setVisibility(View.VISIBLE);} else {infoTextView.setText(R.string.text_empty_repos);infoTextView.setVisibility(View.VISIBLE);}}@Overridepublic void onError(Throwable error) {Log.e(TAG, "Error loading GitHub repos ", error);progressBar.setVisibility(View.GONE);if (error instanceof HttpException&& ((HttpException) error).code() == 404) {infoTextView.setText(R.string.error_username_not_found);} else {infoTextView.setText(R.string.error_loading_repos);}infoTextView.setVisibility(View.VISIBLE);}@Overridepublic void onNext(List<Repository> repositories) {Log.i(TAG, "Repos loaded " + repositories);RepositoryAdapter adapter =(RepositoryAdapter) reposRecycleView.getAdapter();adapter.setRepositories(repositories);adapter.notifyDataSetChanged();}});

MVP

  • 將Presenter與View綁定,并且將用戶響應事件綁定到Presenter中

//Set up presenterpresenter = new MainPresenter();presenter.attachView(this);...// Set up search buttonsearchButton = (ImageButton) findViewById(R.id.button_search);searchButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {presenter.loadRepositories(editTextUsername.getText().toString());}});
  • Presenter中調用Model更新數據,并且調用View中進行重新渲染

public void loadRepositories(String usernameEntered) {String username = usernameEntered.trim();if (username.isEmpty()) return;mainMvpView.showProgressIndicator();if (subscription != null) subscription.unsubscribe();ArchiApplication application = ArchiApplication.get(mainMvpView.getContext());GithubService githubService = application.getGithubService();subscription = githubService.publicRepositories(username).observeOn(AndroidSchedulers.mainThread()).subscribeOn(application.defaultSubscribeScheduler()).subscribe(new Subscriber<List<Repository>>() {@Overridepublic void onCompleted() {Log.i(TAG, "Repos loaded " + repositories);if (!repositories.isEmpty()) {mainMvpView.showRepositories(repositories);} else {mainMvpView.showMessage(R.string.text_empty_repos);}}@Overridepublic void onError(Throwable error) {Log.e(TAG, "Error loading GitHub repos ", error);if (isHttp404(error)) {mainMvpView.showMessage(R.string.error_username_not_found);} else {mainMvpView.showMessage(R.string.error_loading_repos);}}@Overridepublic void onNext(List<Repository> repositories) {MainPresenter.this.repositories = repositories;}});}

MVVM

  • XML中聲明數據綁定

<data><variablename="viewModel"type="uk.ivanc.archimvvm.viewmodel.MainViewModel"/></data>...<EditTextandroid:id="@+id/edit_text_username"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_toLeftOf="@id/button_search"android:hint="@string/hit_username"android:imeOptions="actionSearch"android:inputType="text"android:onEditorAction="@{viewModel.onSearchAction}"android:textColor="@color/white"android:theme="@style/LightEditText"app:addTextChangedListener="@{viewModel.usernameEditTextWatcher}"/>
  • View中綁定ViewModel

super.onCreate(savedInstanceState);binding = DataBindingUtil.setContentView(this, R.layout.main_activity);mainViewModel = new MainViewModel(this, this);binding.setViewModel(mainViewModel);setSupportActionBar(binding.toolbar);setupRecyclerView(binding.reposRecyclerView);
  • ViewModel中進行數據操作

public boolean onSearchAction(TextView view, int actionId, KeyEvent event) {if (actionId == EditorInfo.IME_ACTION_SEARCH) {String username = view.getText().toString();if (username.length() > 0) loadGithubRepos(username);return true;}return false;}public void onClickSearch(View view) {loadGithubRepos(editTextUsernameValue);}public TextWatcher getUsernameEditTextWatcher() {return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence charSequence, int start, int before, int count) {editTextUsernameValue = charSequence.toString();searchButtonVisibility.set(charSequence.length() > 0 ? View.VISIBLE : View.GONE);}@Overridepublic void afterTextChanged(Editable editable) {}};}

Unidirectional User Interface Architecture:單向數據流

Unidirectional User Interface Architecture架構的概念源于后端常見的CROS/Event Sourcing模式,其核心思想即是將應用狀態被統一存放在一個或多個的Store中,并且所有的數據更新都是通過可觀測的Actions觸發,而所有的View都是基于Store中的狀態渲染而來。該架構的最大優勢在于整個應用中的數據流以單向流動的方式從而使得有用更好地可預測性與可控性,這樣可以保證你的應用各個模塊之間的松耦合性。與MVVM模式相比,其解決了以下兩個問題:

  • 避免了數據在多個ViewModel中的冗余與不一致問題

  • 分割了ViewModel的職責,使得ViewModel變得更加Clean

Why not Bidirectional(Two-way DataBinding)?

This means that one change (a user input or API response) can affect the state of an application in many places in the code — for example, two-way data binding. That can be hard to maintain and debug.

  • easier-reasoning-with-unidirectional-dataflow-and-immutable-data

Facebook強調,雙向數據綁定極不利于代碼的擴展與維護。

從具體的代碼實現角度來看,雙向數據綁定會導致更改的不可預期性(UnPredictable),就好像Angular利用Dirty Checking來進行是否需要重新渲染的檢測,這導致了應用的緩慢,簡直就是來砸場子的。而在采用了單向數據流之后,整個應用狀態會變得可預測(Predictable),也能很好地了解當狀態發生變化時到底會有多少的組件發生變化。另一方面,相對集中地狀態管理,也有助于你不同的組件之間進行信息交互或者狀態共享,特別是像Redux這種強調Single Store與SIngle State Tree的狀態管理模式,能夠保證以統一的方式對于應用的狀態進行修改,并且Immutable的概念引入使得狀態變得可回溯。

譬如Facebook在Flux Overview中舉的例子,當我們希望在一個界面上同時展示未讀信息列表與未讀信息的總數目的時候,對于MV*就有點惡心了,特別是當這兩個組件不在同一個ViewModel/Controller中的時候。一旦我們將某個未讀信息標識為已讀,會引起控制已讀信息、未讀信息、未讀信息總數目等等一系列模型的更新。特別是很多時候為了方便我們可能在每個ViewModel/Controller都會設置一個數據副本,這會導致依賴連鎖更新,最終導致不可預測的結果與性能損耗。而在Flux中這種依賴是反轉的,Store接收到更新的Action請求之后對數據進行統一的更新并且通知各個View,而不是依賴于各個獨立的ViewModel/Controller所謂的一致性更新。從職責劃分的角度來看,除了Store之外的任何模塊其實都不知道應該如何處理數據,這就保證了合理的職責分割。這種模式下,當我們創建新項目時,項目復雜度的增長瓶頸也就會更高,不同于傳統的View與ViewLogic之間的綁定,控制流被獨立處理,當我們添加新的特性,新的數據,新的界面,新的邏輯處理模塊時,并不會導致原有模塊的復雜度增加,從而使得整個邏輯更加清晰可控。

這里還需要提及一下,很多人應該是從React開始認知到單向數據流這種架構模式的,而當時Angular 1的緩慢與性能之差令人發指,但是譬如Vue與Angular 2的性能就非常優秀。借用Vue.js官方的說法,

The virtual-DOM approach provides a functional way to describe your view at any point of time, which is really nice. Because it doesn’t use observables and re-renders the entire app on every update, the view is by definition guaranteed to be in sync with the data. It also opens up possibilities to isomorphic JavaScript applications.

Instead of a Virtual DOM, Vue.js uses the actual DOM as the template and keeps references to actual nodes for data bindings. This limits Vue.js to environments where DOM is present. However, contrary to the common misconception that Virtual-DOM makes React faster than anything else, Vue.js actually out-performs React when it comes to hot updates, and requires almost no hand-tuned optimization. With React, you need to implementshouldComponentUpdate everywhere and use immutable data structures to achieve fully optimized re-renders.

總而言之,筆者認為雙向數據流與單向數據流相比,性能上孰優孰劣尚無定論,最大的區別在于單向數據流與雙向數據流相比有更好地可控性,這一點在上文提及的函數響應式編程中也有體現。若論快速開發,筆者感覺雙向數據綁定略勝一籌,畢竟這種View與ViewModel/ViewLogic之間的直接綁定直觀便捷。而如果是注重于全局的狀態管理,希望維護耦合程度較低、可測試性/可擴展性較高的代碼,那么還是單向數據流,即Unidirectional Architecture較為合適。一家之言,歡迎討論。

Flux:數據流驅動的頁面

Flux不能算是絕對的先行者,但是在Unidirectional Architecture中卻是最富盛名的一個,也是很多人接觸到的第一個Unidirectional Architecture。Flux主要由以下幾個部分構成:

  • Stores:存放業務數據和應用狀態,一個Flux中可能存在多個Stores

  • View:層次化組合的React組件

  • Actions:用戶輸入之后觸發View發出的事件

  • Dispatcher:負責分發Actions

根據上述流程,我們可知Flux模式的特性為:

  • Dispatcher:Event Bus中設置有一個單例的Dispatcher,很多Flux的變種都移除了Dispatcher依賴。

  • 只有View使用可組合的組件:在Flux中只有React的組件可以進行層次化組合,而Stores與Actions都不可以進行層次化組合。React組件與Flux一般是松耦合的,因此Flux并不是Fractal,Dispatcher與Stores可以被看做Orchestrator。

  • 用戶事件響應在渲染時聲明:在React的render()函數中,即負責響應用戶交互,也負責注冊用戶事件的處理器

下面我們來看一個具體的代碼對比,首先是以經典的Cocoa風格編寫一個簡單的計數器按鈕:

class ModelCounterconstructor: (@value=1) ->increaseValue: (delta) =>@value += deltaclass ControllerCounterconstructor: (opts) ->@model_counter = opts.model_counter@observers = []getValue: => @model_counter.valueincreaseValue: (delta) =>@model_counter.increaseValue(delta)@notifyObservers()notifyObservers: =>obj.notify(this) for obj in @observersregisterObserver: (observer) =>@observers.push(observer)class ViewCounterButtonconstructor: (opts) ->@controller_counter = opts.controller_counter@button_class = opts.button_class or 'button_counter'@controller_counter.registerObserver(this)render: =>elm = $("<button class=\"#{@button_class}\">#{@controller_counter.getValue()}</button>")elm.click =>@controller_counter.increaseValue(1)return elmnotify: =>$("button.#{@button_class}").replaceWith(=> @render())

上述代碼邏輯用上文提及的MVC模式圖演示就是:

而如果用Flux模式實現,會是下面這個樣子:

# Storeclass CounterStore extends EventEmitterconstructor: ->@count = 0@dispatchToken = @registerToDispatcher()increaseValue: (delta) ->@count += 1getCount: ->return @countregisterToDispatcher: ->CounterDispatcher.register((payload) =>switch payload.typewhen ActionTypes.INCREASE_COUNT@increaseValue(payload.delta))# Actionclass CounterActions@increaseCount: (delta) ->CounterDispatcher.handleViewAction({'type': ActionTypes.INCREASE_COUNT'delta': delta})# ViewCounterButton = React.createClass(getInitialState: ->return {'count': 0}_onChange: ->@setState({count: CounterStore.getCount()})componentDidMount: ->CounterStore.addListener('CHANGE', @_onChange)componentWillUnmount: ->CounterStore.removeListener('CHANGE', @_onChange)render: ->return React.DOM.button({'className': @prop.class}, @state.value))

其數據流圖為:

Redux:集中式的狀態管理

Redux是Flux的所有變種中最為出色的一個,并且也是當前Web領域主流的狀態管理工具,其獨創的理念與功能深刻影響了GUI應用程序架構中的狀態管理的思想。Redux將Flux中單例的Dispatcher替換為了單例的Store,即也是其最大的特性,集中式的狀態管理。并且Store的定義也不是從零開始單獨定義,而是基于多個Reducer的組合,可以把Reducer看做Store Factory。Redux的重要組成部分包括:

  • Singleton Store:管理應用中的狀態,并且提供了一個dispatch(action)函數。

  • Provider:用于監聽Store的變化并且連接像React、Angular這樣的UI框架

  • Actions:基于用戶輸入創建的分發給Reducer的事件

  • Reducers:用于響應Actions并且更新全局狀態樹的純函數

根據上述流程,我們可知Redux模式的特性為:

  • 以工廠模式組裝Stores:Redux允許我以createStore()函數加上一系列組合好的Reducer函數來創建Store實例,還有另一個applyMiddleware()函數可以允許在dispatch()函數執行前后鏈式調用一系列中間件。

  • Providers:Redux并不特定地需要何種UI框架,可以與Angular、React等等很多UI框架協同工作。Redux并不是Fractal,一般來說Store被視作Orchestrator。

  • User Event處理器即可以選擇在渲染函數中聲明,也可以在其他地方進行聲明。

Model-View-Update

又被稱作Elm Architecture,上面所講的Redux就是受到Elm的啟發演化而來,因此MVU與Redux之間有很多的相通之處。MVU使用函數式編程語言Elm作為其底層開發語言,因此該架構可以被看做更純粹的函數式架構。MVU中的基本組成部分有:

  • Model:定義狀態數據結構的類型

  • View:純函數,將狀態渲染為界面

  • Actions:以Mailbox的方式傳遞用戶事件的載體

  • Update:用于更新狀態的純函數

根據上述流程,我們可知Elm模式的特性為:

  • 到處可見的層次化組合:Redux只是在View層允許將組件進行層次化組合,而MVU中在Model與Update函數中也允許進行層次化組合,甚至Actions都可以包含內嵌的子Action

  • Elm屬于Fractal架構:因為Elm中所有的模塊組件都支持層次化組合,即都可以被單獨地導出使用

Model-View-Intent

MVI是一個基于RxJS的響應式單向數據流架構。MVI也是Cycle.js的首選架構,主要由Observable事件流對象與處理函數組成。其主要的組成部分包括:

  • Intent:Observable提供的將用戶事件轉化為Action的函數

  • Model:Observable提供的將Action轉化為可觀測的State的函數

  • View:將狀態渲染為用戶界面的函數

  • Custom Element:類似于React Component那樣的界面組件

根據上述流程,我們可知MVI模式的特性為:

  • 重度依賴于Observables:架構中的每個部分都會被轉化為Observable事件流

  • Intent:不同于Flux或者Redux,MVI中的Actions并沒有直接傳送給Dispatcher或者Store,而是交于正在監聽的Model

  • 徹底的響應式,并且只要所有的組件都遵循MVI模式就能保證整體架構的fractal特性

總結

以上是生活随笔為你收集整理的GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲综合无码一区二区三区 | 欧美人与禽猛交狂配 | 日韩无套无码精品 | 国产精品自产拍在线观看 | 好屌草这里只有精品 | 少妇激情av一区二区 | 国产精品va在线观看无码 | 狠狠cao日日穞夜夜穞av | 亚洲综合伊人久久大杳蕉 | 在线a亚洲视频播放在线观看 | 久久久久成人片免费观看蜜芽 | 97精品国产97久久久久久免费 | 国产av无码专区亚洲a∨毛片 | 成 人 网 站国产免费观看 | 99国产精品白浆在线观看免费 | 国产精品欧美成人 | 国产精品久久久久7777 | 亚洲另类伦春色综合小说 | 成人试看120秒体验区 | 日本免费一区二区三区最新 | 亚洲精品国产第一综合99久久 | 久久国产精品萌白酱免费 | 国精产品一区二区三区 | 日本大香伊一区二区三区 | 国产9 9在线 | 中文 | 人妻无码αv中文字幕久久琪琪布 | 久久99国产综合精品 | 精品人人妻人人澡人人爽人人 | 亚洲综合久久一区二区 | 日本护士xxxxhd少妇 | 人妻中文无码久热丝袜 | 7777奇米四色成人眼影 | 无码av中文字幕免费放 | 亚洲第一网站男人都懂 | 在线视频网站www色 | 红桃av一区二区三区在线无码av | 国产偷抇久久精品a片69 | 国产av剧情md精品麻豆 | 波多野结衣一区二区三区av免费 | 精品国产成人一区二区三区 | 乱中年女人伦av三区 | 99久久久无码国产aaa精品 | 国产亚洲美女精品久久久2020 | 97人妻精品一区二区三区 | 久久亚洲精品成人无码 | а天堂中文在线官网 | 波多野结衣av在线观看 | 国产片av国语在线观看 | 最新版天堂资源中文官网 | 在教室伦流澡到高潮hnp视频 | 啦啦啦www在线观看免费视频 | 欧美freesex黑人又粗又大 | 精品亚洲成av人在线观看 | 国产成人精品无码播放 | 国产人妻精品一区二区三区不卡 | 久久久精品国产sm最大网站 | 国产精品亚洲lv粉色 | 久久97精品久久久久久久不卡 | 国产三级精品三级男人的天堂 | 久久精品国产精品国产精品污 | 国内综合精品午夜久久资源 | 荫蒂添的好舒服视频囗交 | 久久久精品人妻久久影视 | 无码帝国www无码专区色综合 | 中文精品久久久久人妻不卡 | 欧美激情内射喷水高潮 | 亚洲中文无码av永久不收费 | 扒开双腿疯狂进出爽爽爽视频 | 内射巨臀欧美在线视频 | 高潮毛片无遮挡高清免费 | 人妻aⅴ无码一区二区三区 | 亚洲午夜久久久影院 | 亚洲国产日韩a在线播放 | 中文字幕日韩精品一区二区三区 | 妺妺窝人体色www婷婷 | 亚洲色欲色欲天天天www | 精品人妻中文字幕有码在线 | 丝袜 中出 制服 人妻 美腿 | 亚洲精品鲁一鲁一区二区三区 | 午夜精品一区二区三区在线观看 | 精品人妻人人做人人爽夜夜爽 | 日本熟妇大屁股人妻 | 久久精品人妻少妇一区二区三区 | 97夜夜澡人人爽人人喊中国片 | 女人和拘做爰正片视频 | 精品国产一区二区三区四区在线看 | 男女作爱免费网站 | 性史性农村dvd毛片 | 日韩人妻无码一区二区三区久久99 | 亚洲精品www久久久 | 亚洲の无码国产の无码影院 | 国产成人精品无码播放 | 国产成人午夜福利在线播放 | 国产在线精品一区二区高清不卡 | 无套内射视频囯产 | 久久久久成人精品免费播放动漫 | 国产综合在线观看 | 久久精品国产99精品亚洲 | 99久久精品午夜一区二区 | 久久精品国产一区二区三区 | 欧美人与禽zoz0性伦交 | 日韩av无码中文无码电影 | 少妇无套内谢久久久久 | 日本高清一区免费中文视频 | 免费观看激色视频网站 | 亚洲午夜久久久影院 | 国产免费无码一区二区视频 | 内射欧美老妇wbb | 亚洲色偷偷偷综合网 | 18禁黄网站男男禁片免费观看 | 55夜色66夜色国产精品视频 | 久久99国产综合精品 | 久久国产精品精品国产色婷婷 | 亚洲色成人中文字幕网站 | 久久久国产一区二区三区 | 亚洲国产精品毛片av不卡在线 | 少妇被黑人到高潮喷出白浆 | 免费观看又污又黄的网站 | 亚洲 激情 小说 另类 欧美 | 十八禁视频网站在线观看 | 日本在线高清不卡免费播放 | 人人妻人人澡人人爽人人精品 | 性做久久久久久久免费看 | ass日本丰满熟妇pics | 亚洲国产精品成人久久蜜臀 | 日本va欧美va欧美va精品 | 精品水蜜桃久久久久久久 | 国内少妇偷人精品视频 | 中文字幕日韩精品一区二区三区 | 国内精品久久毛片一区二区 | 国产无遮挡又黄又爽又色 | 图片区 小说区 区 亚洲五月 | 日本大乳高潮视频在线观看 | 乌克兰少妇性做爰 | 久久综合给久久狠狠97色 | 欧美黑人性暴力猛交喷水 | 国产成人综合色在线观看网站 | 十八禁视频网站在线观看 | 色五月五月丁香亚洲综合网 | 久久久久se色偷偷亚洲精品av | 国产无av码在线观看 | 免费中文字幕日韩欧美 | 亚洲国产精品久久久天堂 | 午夜无码区在线观看 | 午夜不卡av免费 一本久久a久久精品vr综合 | 福利一区二区三区视频在线观看 | аⅴ资源天堂资源库在线 | 高潮喷水的毛片 | 亚洲欧美日韩综合久久久 | 性开放的女人aaa片 | 成人无码视频在线观看网站 | 女人被男人躁得好爽免费视频 | 国产无套内射久久久国产 | 18禁止看的免费污网站 | 国产婷婷色一区二区三区在线 | 日韩欧美成人免费观看 | 国产亚洲精品久久久久久 | 东北女人啪啪对白 | 欧美国产日韩久久mv | 久久综合九色综合欧美狠狠 | 欧美兽交xxxx×视频 | 国产av无码专区亚洲awww | 天天燥日日燥 | 久久天天躁夜夜躁狠狠 | 日本成熟视频免费视频 | 黑人大群体交免费视频 | 精品一二三区久久aaa片 | 天堂а√在线地址中文在线 | 国内老熟妇对白xxxxhd | 免费无码的av片在线观看 | 国产精品久久福利网站 | 动漫av网站免费观看 | 给我免费的视频在线观看 | 性做久久久久久久免费看 | 人妻人人添人妻人人爱 | 久久久久久国产精品无码下载 | 欧美激情一区二区三区成人 | 日韩精品无码免费一区二区三区 | 国产小呦泬泬99精品 | 日韩精品乱码av一区二区 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 在线观看国产一区二区三区 | 亚洲精品午夜无码电影网 | 国产乱子伦视频在线播放 | 亚洲狠狠婷婷综合久久 | 国产午夜视频在线观看 | 亚洲一区二区观看播放 | 免费看男女做好爽好硬视频 | 色爱情人网站 | 欧美人妻一区二区三区 | 亚洲国产精品久久人人爱 | 亚洲一区二区三区国产精华液 | 国产成人精品无码播放 | 欧美 亚洲 国产 另类 | 成人一区二区免费视频 | 国产黄在线观看免费观看不卡 | 在教室伦流澡到高潮hnp视频 | 精品无码国产自产拍在线观看蜜 | 国产成人一区二区三区在线观看 | 国产又爽又黄又刺激的视频 | 欧美精品在线观看 | 久久久久久九九精品久 | 国产亚av手机在线观看 | 又粗又大又硬又长又爽 | 国产三级久久久精品麻豆三级 | 国产乡下妇女做爰 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 人人爽人人澡人人人妻 | 97无码免费人妻超级碰碰夜夜 | 狠狠色丁香久久婷婷综合五月 | 中文字幕无线码免费人妻 | 日韩在线不卡免费视频一区 | 久久久久99精品成人片 | 欧美性黑人极品hd | 人妻互换免费中文字幕 | 亚洲中文字幕av在天堂 | 一个人看的www免费视频在线观看 | 鲁大师影院在线观看 | 精品久久久久久亚洲精品 | 亚洲欧美色中文字幕在线 | 国产黄在线观看免费观看不卡 | 人人妻人人藻人人爽欧美一区 | 日本精品高清一区二区 | 国产偷抇久久精品a片69 | 99久久久无码国产精品免费 | 日韩精品久久久肉伦网站 | 免费视频欧美无人区码 | 波多野结衣av在线观看 | 人人妻人人澡人人爽欧美一区九九 | 99久久无码一区人妻 | 亚洲の无码国产の无码影院 | 国产精品第一区揄拍无码 | 久久精品视频在线看15 | 国产成人午夜福利在线播放 | 国产 精品 自在自线 | 大肉大捧一进一出好爽视频 | 无码人妻精品一区二区三区下载 | 最近免费中文字幕中文高清百度 | 久久久久免费看成人影片 | 亚洲精品美女久久久久久久 | 丰满人妻一区二区三区免费视频 | aⅴ在线视频男人的天堂 | 国产无遮挡又黄又爽又色 | 中文亚洲成a人片在线观看 | 99在线 | 亚洲 | 久久久久久亚洲精品a片成人 | 色综合久久久无码网中文 | 久久综合给久久狠狠97色 | 无码帝国www无码专区色综合 | 荫蒂被男人添的好舒服爽免费视频 | 午夜熟女插插xx免费视频 | 最新国产麻豆aⅴ精品无码 | 国产亚洲精品久久久ai换 | 国产欧美熟妇另类久久久 | 亚洲中文字幕久久无码 | 国产激情综合五月久久 | 国产xxx69麻豆国语对白 | 久久综合久久自在自线精品自 | 网友自拍区视频精品 | 久久久精品456亚洲影院 | 中文字幕日产无线码一区 | 国内精品久久毛片一区二区 | 漂亮人妻洗澡被公强 日日躁 | 国产精品美女久久久 | 欧美成人免费全部网站 | 精品久久久无码中文字幕 | 亚洲精品久久久久avwww潮水 | 7777奇米四色成人眼影 | 色欲人妻aaaaaaa无码 | 5858s亚洲色大成网站www | 性生交片免费无码看人 | 性啪啪chinese东北女人 | 日本大香伊一区二区三区 | 久久精品国产日本波多野结衣 | 男女下面进入的视频免费午夜 | 久久综合九色综合97网 | 在线精品国产一区二区三区 | 久久久精品国产sm最大网站 | 中文字幕无码人妻少妇免费 | 野狼第一精品社区 | 噜噜噜亚洲色成人网站 | 亚洲 欧美 激情 小说 另类 | 欧美日韩一区二区免费视频 | 久久五月精品中文字幕 | 狠狠色丁香久久婷婷综合五月 | 水蜜桃亚洲一二三四在线 | 麻豆成人精品国产免费 | 久久99精品国产.久久久久 | 人妻有码中文字幕在线 | 亚洲中文字幕久久无码 | 成人一在线视频日韩国产 | 国产av无码专区亚洲awww | 亚洲一区二区三区无码久久 | 久久人人爽人人爽人人片ⅴ | 亚洲色欲色欲欲www在线 | 色综合久久网 | 丰满护士巨好爽好大乳 | 免费国产成人高清在线观看网站 | 黑人大群体交免费视频 | 18精品久久久无码午夜福利 | 成人综合网亚洲伊人 | 偷窥日本少妇撒尿chinese | 少妇久久久久久人妻无码 | 亚洲码国产精品高潮在线 | 国内少妇偷人精品视频免费 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 激情综合激情五月俺也去 | 免费视频欧美无人区码 | 精品无码一区二区三区爱欲 | 中文字幕无码视频专区 | 18禁止看的免费污网站 | 国产午夜手机精彩视频 | 国产av剧情md精品麻豆 | 久久久久免费看成人影片 | av无码电影一区二区三区 | 国产性生大片免费观看性 | 内射巨臀欧美在线视频 | 色婷婷综合中文久久一本 | www国产亚洲精品久久网站 | 亚洲另类伦春色综合小说 | 国产另类ts人妖一区二区 | 精品厕所偷拍各类美女tp嘘嘘 | 国产婷婷色一区二区三区在线 | 67194成是人免费无码 | 亚洲欧美日韩国产精品一区二区 | 天下第一社区视频www日本 | 少妇愉情理伦片bd | 国产人妻精品一区二区三区 | 人妻少妇精品无码专区动漫 | 国产亚洲精品久久久闺蜜 | 亚洲精品一区二区三区四区五区 | 久久www免费人成人片 | 亚洲狠狠色丁香婷婷综合 | 日韩人妻少妇一区二区三区 | 成人欧美一区二区三区黑人 | 国产凸凹视频一区二区 | 国产深夜福利视频在线 | 一本久道高清无码视频 | 亚洲熟女一区二区三区 | 成人aaa片一区国产精品 | 色婷婷综合激情综在线播放 | 精品乱子伦一区二区三区 | 亚欧洲精品在线视频免费观看 | 亚洲一区二区三区偷拍女厕 | 1000部夫妻午夜免费 | 99在线 | 亚洲 | 扒开双腿疯狂进出爽爽爽视频 | 99久久亚洲精品无码毛片 | 免费人成在线观看网站 | 精品一区二区三区无码免费视频 | 亚洲一区av无码专区在线观看 | 永久免费精品精品永久-夜色 | 国产 精品 自在自线 | 又黄又爽又色的视频 | 成人影院yy111111在线观看 | 免费人成网站视频在线观看 | 欧美日韩一区二区综合 | 久久久亚洲欧洲日产国码αv | 亚洲成在人网站无码天堂 | 久久国产精品二国产精品 | 日韩欧美成人免费观看 | 狂野欧美性猛xxxx乱大交 | 巨爆乳无码视频在线观看 | ass日本丰满熟妇pics | 国产福利视频一区二区 | 亚洲一区二区三区含羞草 | 亚洲另类伦春色综合小说 | 麻豆国产人妻欲求不满谁演的 | 在线欧美精品一区二区三区 | 国产香蕉尹人视频在线 | 色婷婷综合中文久久一本 | 亚洲精品一区二区三区婷婷月 | 国产精品久久久久无码av色戒 | 丰满人妻一区二区三区免费视频 | 欧美日韩人成综合在线播放 | 98国产精品综合一区二区三区 | 男人和女人高潮免费网站 | 精品人人妻人人澡人人爽人人 | 成人动漫在线观看 | 97无码免费人妻超级碰碰夜夜 | 国产精品无码永久免费888 | 女人被男人爽到呻吟的视频 | 日韩成人一区二区三区在线观看 | 麻豆国产丝袜白领秘书在线观看 | 人妻无码αv中文字幕久久琪琪布 | 久久久久免费精品国产 | 国产在热线精品视频 | 国产午夜手机精彩视频 | 人妻尝试又大又粗久久 | a在线观看免费网站大全 | 日韩欧美成人免费观看 | 中文字幕+乱码+中文字幕一区 | 在线观看欧美一区二区三区 | 久久视频在线观看精品 | 亚洲精品中文字幕乱码 | 露脸叫床粗话东北少妇 | 国产国语老龄妇女a片 | 日韩精品无码免费一区二区三区 | 欧美黑人巨大xxxxx | 人人妻人人澡人人爽精品欧美 | 中文字幕乱码亚洲无线三区 | 内射后入在线观看一区 | 久久精品一区二区三区四区 | 亚洲精品久久久久久久久久久 | 精品国产一区av天美传媒 | www国产精品内射老师 | 国产精品.xx视频.xxtv | 76少妇精品导航 | 又粗又大又硬又长又爽 | 国产精品久久久av久久久 | 日本精品高清一区二区 | 亚洲综合伊人久久大杳蕉 | 日韩精品乱码av一区二区 | 国产熟妇另类久久久久 | 日日天干夜夜狠狠爱 | 大地资源网第二页免费观看 | 国产精品久久久久久亚洲毛片 | 东北女人啪啪对白 | 国产另类ts人妖一区二区 | 日日躁夜夜躁狠狠躁 | 野狼第一精品社区 | 少妇无码一区二区二三区 | 欧美午夜特黄aaaaaa片 | 动漫av一区二区在线观看 | 99精品无人区乱码1区2区3区 | 国产美女精品一区二区三区 | 玩弄人妻少妇500系列视频 | 亚洲中文字幕av在天堂 | 纯爱无遮挡h肉动漫在线播放 | 亚洲精品综合一区二区三区在线 | 无码精品国产va在线观看dvd | 免费无码的av片在线观看 | 久久亚洲日韩精品一区二区三区 | 无码乱肉视频免费大全合集 | 亚洲无人区一区二区三区 | 久久99精品久久久久婷婷 | 狠狠色噜噜狠狠狠狠7777米奇 | 国产午夜精品一区二区三区嫩草 | 国产精品第一国产精品 | 撕开奶罩揉吮奶头视频 | 午夜不卡av免费 一本久久a久久精品vr综合 | 亚洲国产精品美女久久久久 | 伊在人天堂亚洲香蕉精品区 | 国产小呦泬泬99精品 | 人妻少妇精品无码专区二区 | 扒开双腿疯狂进出爽爽爽视频 | 奇米影视888欧美在线观看 | 久久久久久久久888 | 黑人巨大精品欧美一区二区 | 亚洲中文字幕在线观看 | 精品偷拍一区二区三区在线看 | 久久无码中文字幕免费影院蜜桃 | 丰满人妻精品国产99aⅴ | 熟妇人妻中文av无码 | 在线播放无码字幕亚洲 | 波多野结衣aⅴ在线 | 美女张开腿让人桶 | 日韩精品久久久肉伦网站 | 未满小14洗澡无码视频网站 | 成人性做爰aaa片免费看不忠 | a在线亚洲男人的天堂 | av人摸人人人澡人人超碰下载 | 无遮挡国产高潮视频免费观看 | 色综合天天综合狠狠爱 | 成人无码影片精品久久久 | 风流少妇按摩来高潮 | 国产亲子乱弄免费视频 | 国产性生大片免费观看性 | 国产精品怡红院永久免费 | 天海翼激烈高潮到腰振不止 | 国产人妻人伦精品1国产丝袜 | 老子影院午夜精品无码 | 天堂一区人妻无码 | 色狠狠av一区二区三区 | 内射欧美老妇wbb | 日日麻批免费40分钟无码 | 国产在线精品一区二区三区直播 | 久久人人爽人人人人片 | 娇妻被黑人粗大高潮白浆 | 国产明星裸体无码xxxx视频 | 久久久久亚洲精品男人的天堂 | 特黄特色大片免费播放器图片 | 亚洲中文字幕乱码av波多ji | 国产成人无码区免费内射一片色欲 | 九九在线中文字幕无码 | 国产区女主播在线观看 | 红桃av一区二区三区在线无码av | 欧美黑人性暴力猛交喷水 | 成人一在线视频日韩国产 | 亚洲日本在线电影 | 老熟女乱子伦 | 亚洲精品久久久久中文第一幕 | 99精品国产综合久久久久五月天 | 国内揄拍国内精品人妻 | 色五月丁香五月综合五月 | 精品无码一区二区三区的天堂 | а√天堂www在线天堂小说 | 1000部啪啪未满十八勿入下载 | 欧美丰满熟妇xxxx性ppx人交 | 日日天日日夜日日摸 | 一本大道伊人av久久综合 | 国产精品国产三级国产专播 | 欧美肥老太牲交大战 | 中文字幕 人妻熟女 | 免费人成在线视频无码 | 亚洲人成网站在线播放942 | 亚洲一区二区三区国产精华液 | 在线观看国产一区二区三区 | 日韩视频 中文字幕 视频一区 | 国产亚洲精品久久久久久国模美 | 99久久久无码国产aaa精品 | 国产另类ts人妖一区二区 | 亚洲精品久久久久avwww潮水 | 国产69精品久久久久app下载 | 亚洲精品中文字幕 | 中文字幕无线码 | 国产片av国语在线观看 | 无码人妻丰满熟妇区五十路百度 | 亚洲伊人久久精品影院 | 日韩欧美中文字幕在线三区 | 免费看男女做好爽好硬视频 | 精品无人区无码乱码毛片国产 | 久久99精品国产麻豆蜜芽 | 国产午夜精品一区二区三区嫩草 | 中文无码伦av中文字幕 | 麻豆精品国产精华精华液好用吗 | 丰腴饱满的极品熟妇 | 伊在人天堂亚洲香蕉精品区 | 久久精品中文闷骚内射 | 久久久久免费精品国产 | 5858s亚洲色大成网站www | 麻豆蜜桃av蜜臀av色欲av | 中文字幕无码视频专区 | 又大又黄又粗又爽的免费视频 | 妺妺窝人体色www婷婷 | 国产成人无码av在线影院 | 大肉大捧一进一出视频出来呀 | 亚洲啪av永久无码精品放毛片 | 88国产精品欧美一区二区三区 | 免费无码av一区二区 | 日本护士xxxxhd少妇 | 97无码免费人妻超级碰碰夜夜 | 无码人妻丰满熟妇区五十路百度 | 亚洲欧美综合区丁香五月小说 | 女人和拘做爰正片视频 | 亚洲小说春色综合另类 | 亚洲日韩av一区二区三区中文 | 国产精品va在线观看无码 | 77777熟女视频在线观看 а天堂中文在线官网 | 亚洲欧美日韩成人高清在线一区 | аⅴ资源天堂资源库在线 | 久久久中文久久久无码 | 国产欧美精品一区二区三区 | 熟妇人妻无乱码中文字幕 | 精品人妻人人做人人爽 | 亚洲色欲久久久综合网东京热 | 国内精品久久毛片一区二区 | 一本精品99久久精品77 | 国产精品99久久精品爆乳 | 日本精品少妇一区二区三区 | 亚洲自偷自偷在线制服 | 欧美日本日韩 | 欧美自拍另类欧美综合图片区 | 亚洲日韩中文字幕在线播放 | 日本xxxx色视频在线观看免费 | 亚洲欧洲无卡二区视頻 | 国产莉萝无码av在线播放 | 日日摸夜夜摸狠狠摸婷婷 | 精品 日韩 国产 欧美 视频 | 性生交大片免费看女人按摩摩 | 精品久久久久久亚洲精品 | 亚洲中文无码av永久不收费 | 老子影院午夜精品无码 | 蜜桃av抽搐高潮一区二区 | 中文字幕乱码中文乱码51精品 | 久久天天躁夜夜躁狠狠 | 亚洲精品www久久久 | 狠狠色噜噜狠狠狠狠7777米奇 | 成人性做爰aaa片免费看 | 久久久久av无码免费网 | 国产精品18久久久久久麻辣 | 色窝窝无码一区二区三区色欲 | 人人妻人人澡人人爽人人精品 | 国产亚洲美女精品久久久2020 | 欧洲精品码一区二区三区免费看 | 国产激情无码一区二区 | 久久无码人妻影院 | 精品熟女少妇av免费观看 | 秋霞成人午夜鲁丝一区二区三区 | 日韩 欧美 动漫 国产 制服 | 欧美精品国产综合久久 | 无码帝国www无码专区色综合 | 免费中文字幕日韩欧美 | 亚洲男人av天堂午夜在 | 蜜桃视频韩日免费播放 | 亚洲精品成人福利网站 | 国产精品久久久久久久影院 | 国产成人精品久久亚洲高清不卡 | 亚洲一区二区观看播放 | 欧美精品无码一区二区三区 | 天堂亚洲免费视频 | 国产va免费精品观看 | 国产av人人夜夜澡人人爽麻豆 | 久久久久av无码免费网 | 国产在热线精品视频 | 国产色在线 | 国产 | 婷婷色婷婷开心五月四房播播 | 日韩欧美中文字幕公布 | 成人无码影片精品久久久 | 色偷偷人人澡人人爽人人模 | 奇米影视7777久久精品 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 国精品人妻无码一区二区三区蜜柚 | 日韩视频 中文字幕 视频一区 | 日韩精品一区二区av在线 | 男女爱爱好爽视频免费看 | 欧美大屁股xxxxhd黑色 | 久久亚洲精品中文字幕无男同 | 亚洲欧洲中文日韩av乱码 | yw尤物av无码国产在线观看 | 色五月丁香五月综合五月 | 国产精品久久久 | 欧美真人作爱免费视频 | 久久国产精品偷任你爽任你 | 国产婷婷色一区二区三区在线 | 亚洲日韩一区二区三区 | 亚洲一区二区三区在线观看网站 | 精品国产一区av天美传媒 | 乱中年女人伦av三区 | 亚洲中文字幕久久无码 | 久久久www成人免费毛片 | 最新国产麻豆aⅴ精品无码 | 欧美放荡的少妇 | 亚洲熟妇色xxxxx欧美老妇 | 色偷偷人人澡人人爽人人模 | 久久综合九色综合欧美狠狠 | 天天躁夜夜躁狠狠是什么心态 | 国产精品久久精品三级 | 久久久无码中文字幕久... | 狠狠色色综合网站 | 国产亚洲精品久久久久久国模美 | 国产乱子伦视频在线播放 | 偷窥村妇洗澡毛毛多 | 无码av岛国片在线播放 | 日韩人妻系列无码专区 | 国产免费无码一区二区视频 | 无套内谢老熟女 | 丰满肥臀大屁股熟妇激情视频 | 波多野结衣高清一区二区三区 | 熟妇激情内射com | 综合激情五月综合激情五月激情1 | 免费看少妇作爱视频 | 中文字幕无码av激情不卡 | 少妇性l交大片欧洲热妇乱xxx | 两性色午夜视频免费播放 | 无码毛片视频一区二区本码 | 日本www一道久久久免费榴莲 | 女人被男人爽到呻吟的视频 | 鲁大师影院在线观看 | 亚洲最大成人网站 | 人妻夜夜爽天天爽三区 | 欧美成人午夜精品久久久 | 人人爽人人爽人人片av亚洲 | av无码不卡在线观看免费 | 欧美老熟妇乱xxxxx | 久久综合给合久久狠狠狠97色 | 国产成人一区二区三区别 | a片免费视频在线观看 | 97资源共享在线视频 | 亚洲中文无码av永久不收费 | 日韩精品无码免费一区二区三区 | 国产深夜福利视频在线 | 婷婷综合久久中文字幕蜜桃三电影 | 人妻夜夜爽天天爽三区 | 永久黄网站色视频免费直播 | 四虎永久在线精品免费网址 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 国産精品久久久久久久 | 精品无码国产自产拍在线观看蜜 | 一本色道婷婷久久欧美 | 蜜桃无码一区二区三区 | 亚洲国产av精品一区二区蜜芽 | 亚洲欧美国产精品专区久久 | 久久久久久av无码免费看大片 | 国产特级毛片aaaaaaa高清 | 日韩 欧美 动漫 国产 制服 | 免费人成在线视频无码 | 人妻少妇精品无码专区动漫 | 荫蒂被男人添的好舒服爽免费视频 | 精品久久久久久人妻无码中文字幕 | 国内精品一区二区三区不卡 | 亚洲人成影院在线观看 | 亚洲色大成网站www国产 | 草草网站影院白丝内射 | 欧美freesex黑人又粗又大 | 丰满妇女强制高潮18xxxx | 国产精品久久精品三级 | 妺妺窝人体色www婷婷 | 成人精品视频一区二区三区尤物 | 欧美丰满熟妇xxxx性ppx人交 | 日韩人妻系列无码专区 | 18无码粉嫩小泬无套在线观看 | 亚洲精品一区三区三区在线观看 | 久久久中文久久久无码 | 久久精品无码一区二区三区 | 国产精品亚洲综合色区韩国 | 日韩精品久久久肉伦网站 | 欧美性色19p | 国产手机在线αⅴ片无码观看 | 久久熟妇人妻午夜寂寞影院 | 四虎4hu永久免费 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲人交乣女bbw | 国产人妻精品一区二区三区不卡 | 日韩人妻系列无码专区 | 无码一区二区三区在线观看 | 国产亚洲精品久久久闺蜜 | 亚洲国产欧美在线成人 | 国产精品无码永久免费888 | 人妻互换免费中文字幕 | 一本久久a久久精品vr综合 | 亚洲日本一区二区三区在线 | 在线观看免费人成视频 | 欧洲精品码一区二区三区免费看 | 四虎4hu永久免费 | 欧美35页视频在线观看 | 国内精品一区二区三区不卡 | 无码av岛国片在线播放 | 久久综合九色综合97网 | 久久久久亚洲精品中文字幕 | 国产无av码在线观看 | 爆乳一区二区三区无码 | 天堂久久天堂av色综合 | 中文字幕av伊人av无码av | 美女扒开屁股让男人桶 | 熟妇人妻激情偷爽文 | 乱码午夜-极国产极内射 | 精品厕所偷拍各类美女tp嘘嘘 | 久精品国产欧美亚洲色aⅴ大片 | 日韩av激情在线观看 | www国产亚洲精品久久网站 | 亚洲精品成人av在线 | 秋霞成人午夜鲁丝一区二区三区 | 无码精品国产va在线观看dvd | 日本高清一区免费中文视频 | 成人精品一区二区三区中文字幕 | 丝袜足控一区二区三区 | 久久久久免费看成人影片 | 扒开双腿吃奶呻吟做受视频 | 乱人伦中文视频在线观看 | 欧美35页视频在线观看 | 精品偷拍一区二区三区在线看 | 中文精品久久久久人妻不卡 | 中文字幕色婷婷在线视频 | 亚洲 a v无 码免 费 成 人 a v | 日日碰狠狠躁久久躁蜜桃 | 最新国产乱人伦偷精品免费网站 | 无码午夜成人1000部免费视频 | 久久熟妇人妻午夜寂寞影院 | 欧洲熟妇精品视频 | 国内精品久久久久久中文字幕 | 国产精品人人妻人人爽 | 国产suv精品一区二区五 | 欧美第一黄网免费网站 | а天堂中文在线官网 | 日韩精品无码一本二本三本色 | 香港三级日本三级妇三级 | 无码精品人妻一区二区三区av | 少妇愉情理伦片bd | 久久99精品国产麻豆蜜芽 | 国产精品久久久久久无码 | 国产精品免费大片 | 欧洲极品少妇 | 国产人妻精品一区二区三区不卡 | 无码帝国www无码专区色综合 | 性生交大片免费看女人按摩摩 | 人人澡人人妻人人爽人人蜜桃 | 永久黄网站色视频免费直播 | 亚洲欧美日韩国产精品一区二区 | 亚洲欧美色中文字幕在线 | 少妇一晚三次一区二区三区 | 水蜜桃亚洲一二三四在线 | 免费无码的av片在线观看 | 欧洲熟妇色 欧美 | 久久综合给合久久狠狠狠97色 | 水蜜桃色314在线观看 | 亚洲色大成网站www | 免费播放一区二区三区 | 又色又爽又黄的美女裸体网站 | 欧美日韩在线亚洲综合国产人 | 婷婷综合久久中文字幕蜜桃三电影 | 亚洲一区二区三区国产精华液 | 亚洲色大成网站www国产 | 国产精品无码成人午夜电影 | 中文无码成人免费视频在线观看 | 男女下面进入的视频免费午夜 | 四虎影视成人永久免费观看视频 | 国产成人无码一二三区视频 | 丰满少妇熟乱xxxxx视频 | 久久午夜无码鲁丝片 | 久久成人a毛片免费观看网站 | 扒开双腿疯狂进出爽爽爽视频 | 国产亚洲精品精品国产亚洲综合 | 亚洲区小说区激情区图片区 | 日本成熟视频免费视频 | 性色av无码免费一区二区三区 | 久久久久免费精品国产 | 中文字幕色婷婷在线视频 | 曰韩无码二三区中文字幕 | 久久久久免费看成人影片 | 少妇被粗大的猛进出69影院 | 人妻少妇被猛烈进入中文字幕 | 亚洲精品综合一区二区三区在线 | 少妇久久久久久人妻无码 | 国产精品国产三级国产专播 | 成人无码视频在线观看网站 | 久久亚洲中文字幕精品一区 | 欧美人妻一区二区三区 | 中文无码成人免费视频在线观看 | 色婷婷av一区二区三区之红樱桃 | 色五月丁香五月综合五月 | 四虎国产精品一区二区 | 在线看片无码永久免费视频 | 未满成年国产在线观看 | 野外少妇愉情中文字幕 | 亚洲色欲色欲天天天www | 奇米影视7777久久精品 | www一区二区www免费 | 国产在线一区二区三区四区五区 | 亚洲一区二区三区无码久久 | 2019午夜福利不卡片在线 | 日韩视频 中文字幕 视频一区 | 天堂а√在线中文在线 | 国产精品无码一区二区三区不卡 | 成人女人看片免费视频放人 | 亚洲人交乣女bbw | 国产亚洲精品久久久久久久久动漫 | 日韩精品无码一本二本三本色 | 亚洲午夜福利在线观看 | 丁香花在线影院观看在线播放 | 性色欲情网站iwww九文堂 | 国产精品毛多多水多 | 麻豆成人精品国产免费 | 丁香花在线影院观看在线播放 | 天天爽夜夜爽夜夜爽 | 男女猛烈xx00免费视频试看 | 国产精品高潮呻吟av久久4虎 | 亚洲综合在线一区二区三区 | 亚洲综合色区中文字幕 | 亚洲а∨天堂久久精品2021 | 久久久久久a亚洲欧洲av冫 | 国内精品人妻无码久久久影院蜜桃 | 亚洲爆乳大丰满无码专区 | 亚洲国产成人a精品不卡在线 | www一区二区www免费 | 1000部啪啪未满十八勿入下载 | 性欧美videos高清精品 | 国产精品怡红院永久免费 | 国产人妻人伦精品 | 精品久久综合1区2区3区激情 | 亚洲熟妇色xxxxx亚洲 | 男女猛烈xx00免费视频试看 | 国产香蕉尹人综合在线观看 | 精品久久久久香蕉网 | 国产免费久久精品国产传媒 | 国产色xx群视频射精 | 真人与拘做受免费视频 | 人人妻人人澡人人爽欧美一区九九 | 日本在线高清不卡免费播放 | 丰满诱人的人妻3 | 亚洲日韩av一区二区三区四区 | 国产情侣作爱视频免费观看 | 暴力强奷在线播放无码 | 日本免费一区二区三区最新 | 亚洲天堂2017无码中文 | 激情综合激情五月俺也去 | 丰满少妇高潮惨叫视频 | 色 综合 欧美 亚洲 国产 | 九九久久精品国产免费看小说 | 亚洲成在人网站无码天堂 | 人妻少妇被猛烈进入中文字幕 | 男女性色大片免费网站 | 性色av无码免费一区二区三区 | 一本久道高清无码视频 | 色窝窝无码一区二区三区色欲 | 99久久久无码国产aaa精品 | 成人免费视频视频在线观看 免费 | 亚洲中文字幕无码中字 | 欧美刺激性大交 | 在线播放无码字幕亚洲 | 成人av无码一区二区三区 | 狠狠色丁香久久婷婷综合五月 | 久久久无码中文字幕久... | 久久精品人妻少妇一区二区三区 | 老熟妇乱子伦牲交视频 | 丰满少妇女裸体bbw | 高潮毛片无遮挡高清免费视频 | 丰腴饱满的极品熟妇 | 国产做国产爱免费视频 | 在线播放免费人成毛片乱码 | 中文字幕+乱码+中文字幕一区 | 国产精品久久精品三级 | 1000部啪啪未满十八勿入下载 | 久久熟妇人妻午夜寂寞影院 | 无套内谢的新婚少妇国语播放 | 欧美日韩一区二区三区自拍 | 亚洲日本va中文字幕 | 鲁一鲁av2019在线 | 国产日产欧产精品精品app | 人妻互换免费中文字幕 | 久久午夜无码鲁丝片秋霞 | 久久99精品国产麻豆 | 99久久人妻精品免费二区 | 无码av最新清无码专区吞精 | 国产午夜福利100集发布 | 亚洲国产精华液网站w | 狠狠色噜噜狠狠狠狠7777米奇 | 久久国语露脸国产精品电影 | 国产精品久久久久久亚洲毛片 | 中文字幕无码热在线视频 | 欧美大屁股xxxxhd黑色 | 狠狠亚洲超碰狼人久久 | 一本色道婷婷久久欧美 | 久久精品国产99精品亚洲 | 小sao货水好多真紧h无码视频 | 成人无码精品1区2区3区免费看 | 少妇无套内谢久久久久 | 国产艳妇av在线观看果冻传媒 | 老熟妇仑乱视频一区二区 | 久久久久成人精品免费播放动漫 | 欧美日韩色另类综合 | 国产亚洲精品精品国产亚洲综合 | 久久国内精品自在自线 | 色欲av亚洲一区无码少妇 | 欧美国产日韩久久mv | 无码人妻出轨黑人中文字幕 | 国产成人无码a区在线观看视频app | 国产超级va在线观看视频 | 国产九九九九九九九a片 | 国产亚洲精品久久久ai换 | 日本免费一区二区三区最新 | 偷窥村妇洗澡毛毛多 | 老司机亚洲精品影院 | 一本色道久久综合狠狠躁 | 狂野欧美性猛交免费视频 | 亚洲自偷精品视频自拍 | 少妇性l交大片欧洲热妇乱xxx | 偷窥日本少妇撒尿chinese | 国产亚洲精品久久久久久国模美 | 7777奇米四色成人眼影 | 成人无码影片精品久久久 | 国产成人久久精品流白浆 | 18无码粉嫩小泬无套在线观看 | 欧美精品免费观看二区 | 任你躁在线精品免费 | 永久免费精品精品永久-夜色 | 国内精品一区二区三区不卡 | aⅴ亚洲 日韩 色 图网站 播放 | 国产无遮挡吃胸膜奶免费看 | 4hu四虎永久在线观看 | 国产人妻精品一区二区三区不卡 | 国内精品一区二区三区不卡 | 天下第一社区视频www日本 | 大地资源网第二页免费观看 | 全黄性性激高免费视频 | 十八禁真人啪啪免费网站 | 亚洲成av人片天堂网无码】 | 国产精品永久免费视频 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产成人精品优优av | 欧美人与牲动交xxxx | 在线看片无码永久免费视频 | 中文字幕无码热在线视频 | 亚欧洲精品在线视频免费观看 | 精品欧洲av无码一区二区三区 | 中文无码伦av中文字幕 | 亚洲aⅴ无码成人网站国产app | 久久亚洲a片com人成 | 亚洲一区二区三区 | 女人被爽到呻吟gif动态图视看 | 日日碰狠狠躁久久躁蜜桃 | 国产精品视频免费播放 | 国产莉萝无码av在线播放 | 亚洲精品中文字幕久久久久 | 狂野欧美性猛交免费视频 | 中文字幕无码人妻少妇免费 | 高清不卡一区二区三区 | 国产无套粉嫩白浆在线 | 午夜时刻免费入口 | 日韩精品久久久肉伦网站 | 久久无码专区国产精品s | 国产成人av免费观看 | 亚洲一区二区三区国产精华液 | 亚洲一区二区三区播放 | 亚洲成av人片天堂网无码】 | 成年美女黄网站色大免费全看 | 亚洲爆乳大丰满无码专区 | 人人妻人人澡人人爽人人精品浪潮 | 亚洲中文字幕久久无码 | 午夜精品一区二区三区在线观看 | 熟女体下毛毛黑森林 | 偷窥日本少妇撒尿chinese | 久久五月精品中文字幕 | 十八禁视频网站在线观看 | 国产乱子伦视频在线播放 | 97精品人妻一区二区三区香蕉 | 在线a亚洲视频播放在线观看 | 国产精品无码永久免费888 | 日本在线高清不卡免费播放 | 国产熟妇高潮叫床视频播放 | 奇米影视7777久久精品 | 久久国内精品自在自线 | www国产精品内射老师 | аⅴ资源天堂资源库在线 | 人人澡人人妻人人爽人人蜜桃 | 欧美日本精品一区二区三区 | 麻豆md0077饥渴少妇 | 99国产欧美久久久精品 | 无码人妻少妇伦在线电影 | 4hu四虎永久在线观看 | 久久99精品国产.久久久久 | 亚洲精品国产第一综合99久久 | 国产午夜亚洲精品不卡下载 | 国产69精品久久久久app下载 | 久久久久se色偷偷亚洲精品av | 波多野结衣av一区二区全免费观看 | 欧美日本免费一区二区三区 | 欧美精品免费观看二区 | 久久无码专区国产精品s | 亚洲aⅴ无码成人网站国产app | 中文字幕色婷婷在线视频 | 亚洲精品国产精品乱码不卡 | 天干天干啦夜天干天2017 | 一二三四社区在线中文视频 | www一区二区www免费 | 又大又硬又爽免费视频 | 人人爽人人爽人人片av亚洲 | 欧美人与物videos另类 | 亚洲色大成网站www国产 | 最新国产麻豆aⅴ精品无码 | 久久国内精品自在自线 | 国产97人人超碰caoprom | 天天躁夜夜躁狠狠是什么心态 | 国内少妇偷人精品视频 | 亚洲码国产精品高潮在线 | 国内精品人妻无码久久久影院蜜桃 | 蜜桃视频插满18在线观看 | 麻豆果冻传媒2021精品传媒一区下载 | 久久久久国色av免费观看性色 | 扒开双腿疯狂进出爽爽爽视频 | 亚洲欧美国产精品专区久久 | 国产精品亚洲一区二区三区喷水 | 欧美日韩综合一区二区三区 | 少妇人妻偷人精品无码视频 | 国产亚洲精品久久久久久大师 | 在线亚洲高清揄拍自拍一品区 | 国产午夜无码精品免费看 | 欧美国产日韩久久mv | 国产欧美熟妇另类久久久 | 亚洲色在线无码国产精品不卡 | 精品人妻人人做人人爽 | 久久综合九色综合97网 | 久久久久免费精品国产 | 丰满少妇熟乱xxxxx视频 | 国产精品国产三级国产专播 | 在线观看国产午夜福利片 | 中文字幕无码人妻少妇免费 | 欧洲熟妇色 欧美 | 国产免费无码一区二区视频 | 377p欧洲日本亚洲大胆 | 久久精品丝袜高跟鞋 | 99er热精品视频 | 精品欧洲av无码一区二区三区 | 99re在线播放 | 国内精品久久久久久中文字幕 | 小鲜肉自慰网站xnxx | 亚洲国产精品久久人人爱 | 日日噜噜噜噜夜夜爽亚洲精品 | 久久精品一区二区三区四区 | 大地资源中文第3页 | 精品国产精品久久一区免费式 | 亚洲人亚洲人成电影网站色 | 欧美精品无码一区二区三区 | 天堂无码人妻精品一区二区三区 | 国产精品久久久久久久9999 | 国模大胆一区二区三区 | 精品偷拍一区二区三区在线看 | 色婷婷久久一区二区三区麻豆 | 亚洲午夜福利在线观看 | 日韩少妇内射免费播放 | 东京热男人av天堂 | 自拍偷自拍亚洲精品被多人伦好爽 | 久久人人爽人人爽人人片ⅴ | 性欧美熟妇videofreesex | 国产成人人人97超碰超爽8 | 天天燥日日燥 | 中文字幕人成乱码熟女app | 精品无码一区二区三区爱欲 | 精品久久久无码中文字幕 | 亚洲人成影院在线无码按摩店 | 国产成人av免费观看 | 久久久久亚洲精品男人的天堂 | 国产精品久久福利网站 | 日本熟妇乱子伦xxxx | 国产黑色丝袜在线播放 | 天堂一区人妻无码 | 狠狠亚洲超碰狼人久久 | 欧美亚洲日韩国产人成在线播放 | 人妻少妇精品无码专区动漫 | 少妇性l交大片欧洲热妇乱xxx | 女人被爽到呻吟gif动态图视看 | 性欧美videos高清精品 | 无套内射视频囯产 | 精品乱子伦一区二区三区 | 日韩精品无码一本二本三本色 | 欧美日韩人成综合在线播放 | 色狠狠av一区二区三区 | 亚洲自偷自拍另类第1页 | 亚洲中文字幕在线观看 | 亚洲中文字幕在线观看 | 国产精品久久久久7777 | 欧美 日韩 亚洲 在线 | 欧美一区二区三区视频在线观看 | 波多野42部无码喷潮在线 | 国产人妻大战黑人第1集 | 亚洲成a人片在线观看日本 | 国产精品久久久久久久9999 | 人人妻人人澡人人爽人人精品浪潮 | 无码av岛国片在线播放 | 人人爽人人爽人人片av亚洲 | 波多野结衣一区二区三区av免费 | 精品人妻人人做人人爽 | 国产偷自视频区视频 | 国产美女精品一区二区三区 | 国产精品欧美成人 | 亚洲一区二区三区偷拍女厕 | 国产国产精品人在线视 | 无码人妻少妇伦在线电影 | 欧美日韩在线亚洲综合国产人 | 日本va欧美va欧美va精品 | 四虎国产精品免费久久 | 精品无码国产一区二区三区av | 国产手机在线αⅴ片无码观看 | 国内老熟妇对白xxxxhd | 激情内射亚州一区二区三区爱妻 | 精品熟女少妇av免费观看 | 亚洲а∨天堂久久精品2021 | 内射巨臀欧美在线视频 | 国产人成高清在线视频99最全资源 | 亚洲成av人影院在线观看 | 无码av最新清无码专区吞精 | 国产麻豆精品精东影业av网站 | 男女超爽视频免费播放 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 在线视频网站www色 | 一个人看的视频www在线 | 精品久久久久久亚洲精品 | 亚洲一区二区三区国产精华液 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久www免费人成人片 | 国内精品一区二区三区不卡 | 大乳丰满人妻中文字幕日本 | 国产xxx69麻豆国语对白 | 奇米影视888欧美在线观看 | 亚洲另类伦春色综合小说 | 377p欧洲日本亚洲大胆 | 中文无码成人免费视频在线观看 | 人妻少妇精品无码专区二区 | 亚洲国产欧美在线成人 | 2020最新国产自产精品 | 色一情一乱一伦一视频免费看 | 亚洲热妇无码av在线播放 | 丝袜 中出 制服 人妻 美腿 | 麻豆国产人妻欲求不满谁演的 | 大肉大捧一进一出好爽视频 | 四虎永久在线精品免费网址 | 无码乱肉视频免费大全合集 | 牲欲强的熟妇农村老妇女 | 亚洲七七久久桃花影院 | 美女张开腿让人桶 | 人妻少妇精品久久 | 国内少妇偷人精品视频免费 | 国产麻豆精品一区二区三区v视界 | 亚洲色欲色欲欲www在线 | 激情人妻另类人妻伦 | 色综合视频一区二区三区 | 亚洲一区二区三区偷拍女厕 | 乱码午夜-极国产极内射 | 宝宝好涨水快流出来免费视频 | 日韩欧美群交p片內射中文 | 国产真实夫妇视频 | 精品乱子伦一区二区三区 | 成人亚洲精品久久久久软件 | 亚洲熟悉妇女xxx妇女av | 牲欲强的熟妇农村老妇女视频 | 亚洲 日韩 欧美 成人 在线观看 | 无套内谢老熟女 | 国产精品无码成人午夜电影 | 宝宝好涨水快流出来免费视频 | 人妻无码久久精品人妻 | 日本乱人伦片中文三区 | 久久久久av无码免费网 | 国产熟妇高潮叫床视频播放 | 久久综合狠狠综合久久综合88 | 中文无码成人免费视频在线观看 | 波多野结衣高清一区二区三区 | 久久99精品国产.久久久久 | 四十如虎的丰满熟妇啪啪 | 精品国产一区二区三区四区 | 国产精品18久久久久久麻辣 | 亚洲精品中文字幕久久久久 | 人妻夜夜爽天天爽三区 | av无码久久久久不卡免费网站 | 免费人成在线观看网站 | 又粗又大又硬又长又爽 | 久久久久久av无码免费看大片 | 天天摸天天透天天添 | 水蜜桃色314在线观看 | 国产精品人人爽人人做我的可爱 | 久久综合激激的五月天 | 黑人巨大精品欧美一区二区 | 97无码免费人妻超级碰碰夜夜 | 伊人色综合久久天天小片 | 国精品人妻无码一区二区三区蜜柚 | 97夜夜澡人人双人人人喊 | av人摸人人人澡人人超碰下载 | 亚洲经典千人经典日产 | 人妻天天爽夜夜爽一区二区 | 精品久久综合1区2区3区激情 | 精品国产成人一区二区三区 | av无码电影一区二区三区 | 国内揄拍国内精品少妇国语 | 无码精品人妻一区二区三区av | 色情久久久av熟女人妻网站 | 97久久超碰中文字幕 | 天天拍夜夜添久久精品 | 亚洲国产午夜精品理论片 | 亚洲精品综合五月久久小说 | 久久精品无码一区二区三区 | 久久久久国色av免费观看性色 | 久久视频在线观看精品 | 欧美激情内射喷水高潮 | 学生妹亚洲一区二区 | 亚洲色欲久久久综合网东京热 | 免费中文字幕日韩欧美 | 好爽又高潮了毛片免费下载 | 久久精品国产一区二区三区肥胖 | 捆绑白丝粉色jk震动捧喷白浆 | 18禁止看的免费污网站 | 日韩无套无码精品 | 双乳奶水饱满少妇呻吟 | 日日天干夜夜狠狠爱 | 国产精品99爱免费视频 | 国产特级毛片aaaaaa高潮流水 | 一本加勒比波多野结衣 | 精品久久久久久人妻无码中文字幕 | 国产精品99爱免费视频 | 3d动漫精品啪啪一区二区中 | 2019nv天堂香蕉在线观看 | 日韩 欧美 动漫 国产 制服 | 久久久久久国产精品无码下载 | 天天躁日日躁狠狠躁免费麻豆 | 亚洲最大成人网站 | 天下第一社区视频www日本 | 国产熟妇另类久久久久 | 欧美阿v高清资源不卡在线播放 | 欧美成人家庭影院 | 国产又爽又黄又刺激的视频 | 曰本女人与公拘交酡免费视频 | 亚洲综合色区中文字幕 | 久久综合色之久久综合 | 无码国内精品人妻少妇 | 精品无码一区二区三区的天堂 | 久久综合九色综合欧美狠狠 | 粗大的内捧猛烈进出视频 | 久久国产精品萌白酱免费 | 亚洲成a人片在线观看无码 | 日日摸日日碰夜夜爽av | 色综合视频一区二区三区 | 正在播放老肥熟妇露脸 | 亚洲精品美女久久久久久久 | 最近中文2019字幕第二页 | 无码人妻av免费一区二区三区 | 天天躁日日躁狠狠躁免费麻豆 | 欧美人与牲动交xxxx | 少妇太爽了在线观看 | 国产亚洲精品精品国产亚洲综合 | 巨爆乳无码视频在线观看 | 久久亚洲a片com人成 | 野外少妇愉情中文字幕 | 亚洲精品国产精品乱码不卡 | 麻豆md0077饥渴少妇 | 精品乱子伦一区二区三区 | 久久亚洲精品中文字幕无男同 | 日本一区二区三区免费高清 | 国产熟妇另类久久久久 | 99精品视频在线观看免费 | aⅴ在线视频男人的天堂 | 国产亚洲日韩欧美另类第八页 | 婷婷综合久久中文字幕蜜桃三电影 | 国产三级精品三级男人的天堂 | 老司机亚洲精品影院无码 | 欧美三级不卡在线观看 | 色老头在线一区二区三区 | 国产成人无码a区在线观看视频app | 成人一在线视频日韩国产 | 国产又爽又猛又粗的视频a片 | 午夜福利一区二区三区在线观看 | 日本一卡2卡3卡四卡精品网站 | 亚洲人成影院在线观看 | 呦交小u女精品视频 | 久久精品国产99久久6动漫 | 香蕉久久久久久av成人 | 国产精品久久久 | 亚洲一区二区三区偷拍女厕 | 久久久久免费看成人影片 | 又粗又大又硬毛片免费看 | 国产一精品一av一免费 | 小sao货水好多真紧h无码视频 | 国产精品久久久久影院嫩草 | 99精品国产综合久久久久五月天 | 免费无码肉片在线观看 | 丰满少妇高潮惨叫视频 | 亚洲欧美日韩成人高清在线一区 | 国产熟女一区二区三区四区五区 | 亚洲人成人无码网www国产 | 欧洲欧美人成视频在线 | 国产精品久久久一区二区三区 | 国产av无码专区亚洲awww | 午夜无码区在线观看 | 无码人妻久久一区二区三区不卡 | 亚洲国产精华液网站w | 乱码av麻豆丝袜熟女系列 | 日产精品99久久久久久 | 无码av岛国片在线播放 | 国产精品沙发午睡系列 | 成 人 网 站国产免费观看 | 精品无码av一区二区三区 | 男女爱爱好爽视频免费看 | 国产香蕉97碰碰久久人人 | 少妇的肉体aa片免费 | 午夜精品久久久久久久久 | 亚洲啪av永久无码精品放毛片 | a国产一区二区免费入口 | 国产精品无套呻吟在线 | 色狠狠av一区二区三区 | 人人爽人人澡人人人妻 | 亚洲区欧美区综合区自拍区 | 亚洲人成影院在线观看 | 欧美人与禽zoz0性伦交 | 久久综合色之久久综合 | 国产成人av免费观看 | 欧美人妻一区二区三区 | 99精品国产综合久久久久五月天 | 中文无码成人免费视频在线观看 | 欧美乱妇无乱码大黄a片 | 波多野结衣乳巨码无在线观看 | 中文字幕 人妻熟女 | 天堂久久天堂av色综合 | 亲嘴扒胸摸屁股激烈网站 | 日韩在线不卡免费视频一区 | 亚洲精品一区国产 | 免费视频欧美无人区码 | 老头边吃奶边弄进去呻吟 | 亚洲一区av无码专区在线观看 | 欧美人与动性行为视频 | 丰满人妻精品国产99aⅴ | 国产猛烈高潮尖叫视频免费 | 99久久婷婷国产综合精品青草免费 | 成年女人永久免费看片 | 国产av无码专区亚洲a∨毛片 | 亚洲成熟女人毛毛耸耸多 | 亚洲国产精品一区二区第一页 | 国产欧美亚洲精品a | 给我免费的视频在线观看 | 55夜色66夜色国产精品视频 | 亚洲经典千人经典日产 | 丰满护士巨好爽好大乳 | 俄罗斯老熟妇色xxxx | 在线看片无码永久免费视频 | www国产精品内射老师 | 日韩精品成人一区二区三区 | 成人试看120秒体验区 | 伊人久久大香线蕉亚洲 | 18精品久久久无码午夜福利 | 伊在人天堂亚洲香蕉精品区 | 精品成在人线av无码免费看 | 成人精品视频一区二区 | 国产精品久久国产精品99 | 无码一区二区三区在线观看 | 久久午夜无码鲁丝片 | 国产精品成人av在线观看 | 少妇久久久久久人妻无码 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 国产香蕉尹人综合在线观看 | 日本一卡2卡3卡四卡精品网站 | 国产亚洲精品久久久久久 | 亚洲精品一区国产 | 精品国产国产综合精品 | 欧美freesex黑人又粗又大 | 人妻少妇精品无码专区二区 | 中文字幕 人妻熟女 | 熟妇激情内射com | 水蜜桃亚洲一二三四在线 | 国产精品va在线播放 | 亚洲精品久久久久中文第一幕 | 免费看少妇作爱视频 | 乱人伦人妻中文字幕无码久久网 | 久久久久人妻一区精品色欧美 | 婷婷五月综合缴情在线视频 | 奇米影视7777久久精品人人爽 | 亚洲国产午夜精品理论片 | 精品国产麻豆免费人成网站 | 中文无码成人免费视频在线观看 | 国产舌乚八伦偷品w中 | 中文字幕无码免费久久9一区9 | 精品一二三区久久aaa片 | 欧美国产日韩亚洲中文 | 亚洲成熟女人毛毛耸耸多 | 国产乱人伦av在线无码 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 1000部啪啪未满十八勿入下载 | 99久久久无码国产aaa精品 | 丝袜美腿亚洲一区二区 | 图片小说视频一区二区 | 亚洲一区二区观看播放 | 黑人粗大猛烈进出高潮视频 | 久久久国产精品无码免费专区 | 综合人妻久久一区二区精品 | 伊人久久婷婷五月综合97色 | 国产精品99久久精品爆乳 | 无码帝国www无码专区色综合 | 特黄特色大片免费播放器图片 | 国产亚av手机在线观看 | 成人av无码一区二区三区 | 久久久久99精品成人片 | 四虎国产精品一区二区 | 在线亚洲高清揄拍自拍一品区 | 欧美人与禽猛交狂配 | 人妻插b视频一区二区三区 | 日本肉体xxxx裸交 | 一区二区三区乱码在线 | 欧洲 | 日韩av无码一区二区三区不卡 | 欧美日韩一区二区综合 | 色综合久久网 | 狂野欧美性猛xxxx乱大交 | 极品尤物被啪到呻吟喷水 | 久久亚洲日韩精品一区二区三区 | 人妻夜夜爽天天爽三区 | 午夜男女很黄的视频 | 亚洲一区二区三区香蕉 | 97色伦图片97综合影院 | 午夜肉伦伦影院 | 国产另类ts人妖一区二区 | 人人妻人人澡人人爽人人精品 | а√天堂www在线天堂小说 | 一本一道久久综合久久 | 我要看www免费看插插视频 | 久久人人爽人人爽人人片ⅴ | 曰韩少妇内射免费播放 | 99er热精品视频 | 免费观看的无遮挡av | 国产精品多人p群无码 | 久久精品国产99精品亚洲 | 粉嫩少妇内射浓精videos | 免费乱码人妻系列无码专区 | 国产午夜手机精彩视频 | 亚洲娇小与黑人巨大交 | 中文字幕av无码一区二区三区电影 | 国产亚洲精品精品国产亚洲综合 | 国产亚洲精品久久久久久久久动漫 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 欧美亚洲国产一区二区三区 | 狠狠色丁香久久婷婷综合五月 | 亚洲精品国产精品乱码视色 | 真人与拘做受免费视频 | 精品日本一区二区三区在线观看 | 日韩精品久久久肉伦网站 | 男人的天堂2018无码 | av无码不卡在线观看免费 | 欧美 日韩 人妻 高清 中文 | 国产精品久久久久久亚洲影视内衣 | 撕开奶罩揉吮奶头视频 | 最新国产麻豆aⅴ精品无码 | 漂亮人妻洗澡被公强 日日躁 | 男女作爱免费网站 | 76少妇精品导航 | 中文字幕乱码中文乱码51精品 | 国产艳妇av在线观看果冻传媒 | 少妇高潮一区二区三区99 | 国精产品一区二区三区 | 久久五月精品中文字幕 | 伊人色综合久久天天小片 | 国产午夜手机精彩视频 | 曰韩少妇内射免费播放 | 人人妻人人澡人人爽人人精品浪潮 | 国产精品对白交换视频 | 成人三级无码视频在线观看 | 精品人妻av区 | 人人妻人人澡人人爽欧美一区 | 99久久99久久免费精品蜜桃 | 日日碰狠狠躁久久躁蜜桃 | 亚洲爆乳无码专区 | 夜精品a片一区二区三区无码白浆 | 无码国产激情在线观看 | 国产明星裸体无码xxxx视频 | 青草视频在线播放 | 欧美人与物videos另类 | 国产农村乱对白刺激视频 | 人妻少妇精品视频专区 | 无码播放一区二区三区 | 又大又硬又爽免费视频 | 日本又色又爽又黄的a片18禁 | av人摸人人人澡人人超碰下载 | 3d动漫精品啪啪一区二区中 | 丰满少妇高潮惨叫视频 | 亚洲熟悉妇女xxx妇女av | 国产高清av在线播放 | a片免费视频在线观看 | 日产国产精品亚洲系列 | 久久99精品国产.久久久久 | 少女韩国电视剧在线观看完整 | 精品国精品国产自在久国产87 | 国产欧美熟妇另类久久久 | 蜜桃臀无码内射一区二区三区 | 欧美性生交活xxxxxdddd | 日本成熟视频免费视频 | 亚洲日韩一区二区三区 | 无码人妻丰满熟妇区毛片18 | 国产黑色丝袜在线播放 | 国产高潮视频在线观看 | 人妻人人添人妻人人爱 | www一区二区www免费 | 亚洲啪av永久无码精品放毛片 | 午夜不卡av免费 一本久久a久久精品vr综合 | 日本一区二区三区免费播放 | 一二三四在线观看免费视频 | 久久精品人人做人人综合试看 | 日本一卡2卡3卡四卡精品网站 | 少妇性l交大片欧洲热妇乱xxx | 99久久人妻精品免费二区 | 国产精品久久久久久无码 | 欧美兽交xxxx×视频 | 久久国产精品偷任你爽任你 | 亚洲精品一区三区三区在线观看 | 精品成人av一区二区三区 | 亚洲国产精品成人久久蜜臀 | 亚洲精品一区三区三区在线观看 | 亚洲娇小与黑人巨大交 | 98国产精品综合一区二区三区 | 夜夜高潮次次欢爽av女 | 亚洲中文字幕无码中文字在线 | 99久久精品国产一区二区蜜芽 | 午夜免费福利小电影 | 亚洲最大成人网站 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 伊人久久大香线蕉午夜 | 国产97在线 | 亚洲 | 成年女人永久免费看片 | 99国产精品白浆在线观看免费 | 久久aⅴ免费观看 | 国内精品久久久久久中文字幕 | 亚洲经典千人经典日产 | 亚洲精品鲁一鲁一区二区三区 | 中文字幕无码免费久久99 | 撕开奶罩揉吮奶头视频 | 色婷婷久久一区二区三区麻豆 | 亚洲高清偷拍一区二区三区 | 强奷人妻日本中文字幕 | 欧美老妇与禽交 | 欧美性猛交内射兽交老熟妇 | 青青草原综合久久大伊人精品 | 久久综合久久自在自线精品自 | 国产人妻人伦精品 | 亚洲另类伦春色综合小说 | 色 综合 欧美 亚洲 国产 | 日日夜夜撸啊撸 | 久久99精品久久久久婷婷 | 亚洲精品综合一区二区三区在线 | 啦啦啦www在线观看免费视频 | 国产av一区二区三区最新精品 | 亚洲欧美中文字幕5发布 | 综合网日日天干夜夜久久 | 国产高清不卡无码视频 | 色综合久久久无码网中文 | 久久午夜夜伦鲁鲁片无码免费 | 黑森林福利视频导航 | 日本大香伊一区二区三区 | 亚洲小说春色综合另类 | 久久视频在线观看精品 | 全球成人中文在线 | 麻花豆传媒剧国产免费mv在线 | 国产精华av午夜在线观看 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 奇米影视7777久久精品人人爽 | 少妇久久久久久人妻无码 | 中文字幕人成乱码熟女app | 97精品国产97久久久久久免费 | 日本丰满熟妇videos | 成人精品视频一区二区 | 天堂а√在线地址中文在线 | 粗大的内捧猛烈进出视频 | 夜先锋av资源网站 | 日韩av无码中文无码电影 | 天天摸天天透天天添 | 任你躁在线精品免费 | 精品国产一区av天美传媒 | 九月婷婷人人澡人人添人人爽 | 最新国产乱人伦偷精品免费网站 | 欧美国产日韩亚洲中文 | 狠狠色丁香久久婷婷综合五月 | 性欧美videos高清精品 | 国产亚洲人成a在线v网站 | 亚洲综合无码久久精品综合 | 久久人妻内射无码一区三区 | 久久国产劲爆∧v内射 | 中文无码成人免费视频在线观看 | 成人无码精品1区2区3区免费看 | 骚片av蜜桃精品一区 | 麻豆精品国产精华精华液好用吗 | 中文字幕乱码人妻无码久久 | 97精品人妻一区二区三区香蕉 | 久久99国产综合精品 | 天堂а√在线地址中文在线 | 久久人人爽人人人人片 | 中文字幕精品av一区二区五区 | 乱人伦中文视频在线观看 | 久久99精品久久久久久 | 国产午夜无码视频在线观看 | 欧美老熟妇乱xxxxx | 国产精品久久久一区二区三区 | 亚洲狠狠色丁香婷婷综合 | 97无码免费人妻超级碰碰夜夜 | 福利一区二区三区视频在线观看 | 欧洲欧美人成视频在线 | av在线亚洲欧洲日产一区二区 | 乱码av麻豆丝袜熟女系列 | 国产内射爽爽大片视频社区在线 | 国产69精品久久久久app下载 | 精品国精品国产自在久国产87 | 亚洲人成人无码网www国产 | 樱花草在线社区www | 国产香蕉97碰碰久久人人 | 天堂亚洲免费视频 | 亚洲色大成网站www国产 | 黑人玩弄人妻中文在线 | 欧美性猛交内射兽交老熟妇 | 水蜜桃av无码 | 国产在线精品一区二区三区直播 | 国产高潮视频在线观看 | 免费观看激色视频网站 | 无码人妻丰满熟妇区毛片18 | 欧美人与禽猛交狂配 | 精品国产一区二区三区四区 | 国产超级va在线观看视频 | 日韩精品无码一区二区中文字幕 | 又黄又爽又色的视频 | 国产av人人夜夜澡人人爽麻豆 | 欧美阿v高清资源不卡在线播放 | 久久久久久久女国产乱让韩 | 欧美 丝袜 自拍 制服 另类 | 蜜桃av抽搐高潮一区二区 | 国产乱人伦偷精品视频 | 妺妺窝人体色www婷婷 | 波多野结衣av在线观看 | av小次郎收藏 | 一个人看的www免费视频在线观看 | 欧美喷潮久久久xxxxx | 乱人伦人妻中文字幕无码 | 国产精品香蕉在线观看 | 国产后入清纯学生妹 | 黄网在线观看免费网站 | 久久国产自偷自偷免费一区调 | 成人av无码一区二区三区 | 亚洲国产精品毛片av不卡在线 | 免费无码av一区二区 |