国产自产第一-国产自产对白一区-国产自产精品-国产自产区44页-国产自产在线-国产自产自拍-国产自产自拍视频-国产自精品

金喜正规买球

什么是觀察者模式?如何在Java 8中實現觀察者模式?

轉帖|使用教程|編輯:我只采一朵|2016-03-01 11:40:38.000|閱讀 597 次

概述:本文主要介紹通過使用 Java8 架構實現觀察者模式,并在此基礎上進一步探討關于經典模式的復雜問題,包括匿名內部類、lambda 表達式、線程安全以及非平凡耗時長的觀察者實現。本文內容雖然并不全面,很多這種模式所涉及的復雜問題,遠不是一篇文章就能說清的。但是讀完本文,讀者能 了解什么是觀察者模式,它在Java中的通用性以及如何處理在 Java 中實現觀察者模式時的一些常見問題。

# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>

察者(Observer)模式又名發布-訂閱(Publish/Subscribe)模式,是四人組(GoF,即 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides)在1994合著的《設計模式:可復用面向對象軟件的基礎》中提出的(詳見書中293-313頁)。盡管這種模式已經有相當長的歷史, 它仍然廣泛適用于各種場景,甚至成為了標準Java庫的一個組成部分。目前雖然已經有大量關于觀察者模式的文章,但它們都專注于在 Java 中的實現,卻忽視了開發者在Java中使用觀察者模式時遇到的各種問題。

本文的寫作初衷就是為了填補這一空白:本文主要介紹通過使用 Java8 架構實現觀察者模式,并在此基礎上進一步探討關于經典模式的復雜問題,包括匿名內部類、lambda 表達式、線程安全以及非平凡耗時長的觀察者實現。本文內容雖然并不全面,很多這種模式所涉及的復雜問題,遠不是一篇文章就能說清的。但是讀完本文,讀者能 了解什么是觀察者模式,它在Java中的通用性以及如何處理在 Java 中實現觀察者模式時的一些常見問題。

觀察者模式

根據 GoF 提出的經典定義,觀察者模式的主旨是:

定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新。

什么意思呢?很多軟件應用中,對象之間的狀態都是互相依賴的。例如,如果一個應用專注于數值數據加工,這個數據也許會通過圖形用戶界面(GUI)的表格或圖 表來展現或者兩者同時使用,也就是說,當底層數據更新時,相應的 GUI 組件也要更新。問題的關鍵在于如何做到底層數據更新時 GUI 組件也隨之更新,同時盡量減小 GUI 組件和底層數據的耦合度。

一種簡單且不可擴展的解決方案是給管理這些底層數據的對象該表格和圖像 GUI 組件的引用,使得對象可以在底層數據變化時能夠通知 GUI 組件。顯然,對于處理有更多 GUI 組件的復雜應用,這個簡單的解決方案很快顯示出其不足。例如,有20個 GUI 組件都依賴于底層數據,那么管理底層數據的對象就需要維護指向這20個組件的引用。隨著依賴于相關數據的對象數量的增加,數據管理和對象之間的耦合度也變 得難以控制。

另一個更好的解決方案是允許對象注冊獲取感興趣數據更新的權限,當數據變化時,數據管理器就會通知這些對象。通俗地說就是,讓 感興趣的數據對象告訴管理器:“當數據變化時請通知我”。此外,這些對象不僅可以注冊獲取更新通知,也可以取消注冊,保證數據管理器在數據變化時不再通知 該對象。在 GoF 的原始定義中,注冊獲取更新的對象叫作“觀察者”(observer),對應的數據管理器叫作“目標”(Subject),觀察者感興趣的數據叫作“目標 狀態”,注冊過程叫“添加”(attach),撤銷觀察的過程叫“移除”(detach)。前文已經提到觀察者模式又叫發布-訂閱模式,可以理解為客戶訂 閱關于目標的觀察者,當目標狀態更新時,目標把這些更新發布給訂閱者(這種設計模式擴展為通用架構,稱為發布——訂閱架構)。這些概念可以用下面的類圖表示:

Java8觀察者模式

具體觀察者(ConcereteObserver)用來接收更新的狀態變化,同時將指向具體主題(ConcereteSubject)的引用傳遞給它的構 造函數。這為具體觀察者提供了指向具體主題的引用,在狀態變化時可由此獲得更新。簡單來說,具體觀察者會被告知主題更新,同時用其構造函數中的引用來獲取 具體主題的狀態,最后將這些檢索狀態對象存儲在具體觀察者的觀察狀態(observerState)屬性下。這一過程如下面的序列圖所示:

Java8觀察者模式

經典模式的專業化

盡管觀察者模式是通用的,但也有很多專業化的模式,最常見是以下兩種:

  1. 為State對象提供一個參數,傳給觀察者調用的Update方法。在經典模式下,當觀察者被通知Subject狀態發生變化后,會直接從 Subject獲得其更新后狀態。這要求觀察者保存指向獲取狀態的對象引用。這樣就形成了一個循環引用,ConcreteSubject的引用指向其觀察 者列表,ConcreteObserver的引用指向能獲得主題狀態的ConcreteSubject。除了獲得更新的狀態,觀察者和其注冊監聽的 Subject間并沒有聯系,觀察者關心的是State對象,而非Subject本身。也就是說,很多情況下都將ConcreteObserver和 ConcreteSubject強行聯系一起,相反,當ConcreteSubject調用Update函數時,將State對象傳遞給 ConcreteObserver,二者就無需關聯。ConcreteObserver和State對象之間關聯減小了觀察者和State之間的依賴程度 (關聯和依賴的更多區別請參見Martin Fowler’s的文章)。

  2. 將Subject抽象類和ConcreteSubject合并到一個 singleSubject類中。多數情況下,Subject使用抽象類并不會提升程序的靈活性和可擴展性,因此,將這一抽象類和具體類合并簡化了設計。

這兩個專業化的模式組合后,其簡化類圖如下:

Java8觀察者模式

在這些專業化的模式中,靜態類結構大大簡化,類之間的相互作用也得以簡化。此時的序列圖如下:

Java8觀察者模式

專業化模式另一特點是刪除了 ConcreteObserver 的成員變量 observerState。有時候具體觀察者并不需要保存Subject的最新狀態,而只需要監測狀態更新時 Subject 的狀態。例如,如果觀察者將成員變量的值更新到標準輸出上,就可以刪除 observerState,這樣一來就刪除了ConcreteObserver和State類之間的關聯。

更常見的命名規則

經典模式甚至是前文提到的專業化模式都用的是attach,detach和observer等術語,而Java實現中很多都是用的不同的詞典,包括 register,unregister,listener等。值得一提的是State是listener需要監測變化的所有對象的統稱,狀態對象的具體 名稱需要看觀察者模式用到的場景。例如,在listener監聽事件發生場景下的觀察者模式,已注冊的listener將會在事件發生時收到通知,此時的 狀態對象就是event,也就是事件是否發生。

平時實際應用中目標的命名很少包含Subject。例如,創建一個關于動物園的應用,注冊多 個監聽器用于觀察Zoo類,并在新動物進入動物園時收到通知。該案例中的目標是Zoo類,為了和所給問題域保持術語一致,將不會用到Subject這樣的 詞匯,也就是說Zoo類不會命名為ZooSubject。

監聽器的命名一般都會跟著Listener后綴,例如前文提到的監測新動物加入的 監聽器會命名為AnimalAddedListener。類似的,register,、unregister和notify等函數命名常會以其對應的監聽 器名作后綴,例如AnimalAddedListener的register、unregister、notify函數會被命名為 registerAnimalAddedListener、 unregisterAnimalAddedListener和notifyAnimalAddedListeners,需要注意的是notify函數名 的s,因為notify函數處理的是多個而非單一監聽器。

這種命名方式會顯得冗長,而且通常一個subject會注冊多個類型的監聽器,如 前面提到的動物園的例子,Zoo內除了注冊監聽動物新增的監聽器,還需注冊監聽動物減少監聽器,此時就會有兩種register函數: (registerAnimalAddedListener和 registerAnimalRemovedListener,這種方式處理,監聽器的類型作為一個限定符,表示其應觀察者的類型。另一解決方案是創建一 個registerListener函數然后重載,但是方案一能更方便的知道哪個監聽器正在監聽,重載是比較小眾的做法。

另一慣用語法是用on前綴而不是update,例如update函數命名為onAnimalAdded而不是updateAnimalAdded。這種情況在監聽器獲得一個序列的通知時更常見,如向list中新增一個動物,但很少用于更新一個單獨的數據,比如動物的名字。

接下來本文將使用Java的符號規則,雖然符號規則不會改變系統的真實設計和實現,但是使用其他開發者都熟悉的術語是很重要的開發準則,因此要熟悉上文描述的Java中的觀察者模式符號規則。下文將在Java8環境下用一個簡單例子來闡述上述概念。

一個簡單的實例

還是前面提到的動物園的例子,使用Java8的API接口實現一個簡單的系統,說明觀察者模式的基本原理。問題描述為:

創建一個系統zoo,允許用戶監聽和撤銷監聽添加新對象animal的狀態,另外再創建一個具體監聽器,負責輸出新增動物的name。

根據前面對觀察者模式的學習知道實現這樣的應用需要創建4個類,具體是:

  1. Zoo類:即模式中的主題,負責存儲動物園中的所有動物,并在新動物加入時通知所有已注冊的監聽器。

  2. Animal類:代表動物對象。

  3. AnimalAddedListener類:即觀察者接口。

  4. PrintNameAnimalAddedListener:具體的觀察者類,負責輸出新增動物的name。

首先我們創建一個Animal類,它是一個包含name成員變量、構造函數、getter和setter方法的簡單Java對象,代碼如下:

public class Animal {
    private String name;
    public Animal (String name) {
        this.name = name;
    }
    public String getName () {
        return this.name;
    }
    public void setName (String name) {
        this.name = name;
    }
}

用這個類代表動物對象,接下來就可以創建AnimalAddedListener接口了:

public interface AnimalAddedListener {
    public void onAnimalAdded (Animal animal);
}

前面兩個類很簡單,就不再詳細介紹,接下來創建Zoo類:

public class Zoo {
    private List<animal> animals = new ArrayList<>();
    private List<animaladdedlistener> listeners = new ArrayList<>();
    public void addAnimal (Animal animal) {
        // Add the animal to the list of animals
        this.animals.add(animal);
        // Notify the list of registered listeners
        this.notifyAnimalAddedListeners(animal);
    }
    public void registerAnimalAddedListener (AnimalAddedListener listener) {
        // Add the listener to the list of registered listeners
        this.listeners.add(listener);
    }
    public void unregisterAnimalAddedListener (AnimalAddedListener listener) {
        // Remove the listener from the list of the registered listeners
        this.listeners.remove(listener);
    }
    protected void notifyAnimalAddedListeners (Animal animal) {
        // Notify each of the listeners in the list of registered listeners
        this.listeners.forEach(listener -> listener.updateAnimalAdded(animal));
    }
}

這個類比前面兩個都復雜,其包含兩個list,一個用來存儲動物園中所有動物,另一個用來存儲所有的監聽器,鑒于animals和listener 集合存儲的對象都很簡單,本文選擇了ArrayList來存儲。存儲監聽器的具體數據結構要視問題而定,比如對于這里的動物園問題,如果監聽器有優先級, 那就應該選擇其他的數據結構,或者重寫監聽器的register算法。

注冊和移除的實現都是簡單的委托方式:各個監聽器作為參數從監聽者的 監聽列表增加或者移除。notify函數的實現與觀察者模式的標準格式稍微偏離,它包括輸入參數:新增加的animal,這樣一來notify函數就可以 把新增加的animal引用傳遞給監聽器了。用streams API的forEach函數遍歷監聽器,對每個監聽器執行theonAnimalAdded函數。

在addAnimal函數中,新增的 animal對象和監聽器各自添加到對應list。如果不考慮通知過程的復雜性,這一邏輯應包含在方便調用的方法中,只需要傳入指向新增animal對象 的引用即可,這就是通知監聽器的邏輯實現封裝在notifyAnimalAddedListeners函數中的原因,這一點在addAnimal的實現中 也提到過。

除了notify函數的邏輯問題,需要強調一下對notify函數可見性的爭議問題。在經典的觀察者模型中,如GoF在設計模式 一書中第301頁所說,notify函數是public型的,然而盡管在經典模式中用到,這并不意味著必須是public的。選擇可見性應該基于應用,例 如本文的動物園的例子,notify函數是protected類型,并不要求每個對象都可以發起一個注冊觀察者的通知,只需保證對象能從父類繼承該功能即 可。當然,也并非完全如此,需要弄清楚哪些類可以激活notify函數,然后再由此確定函數的可見性。

接下來需要實現PrintNameAnimalAddedListener類,這個類用System.out.println方法將新增動物的name輸出,具體代碼如下:

public class PrintNameAnimalAddedListener implements AnimalAddedListener {
    @Override
    public void updateAnimalAdded (Animal animal) {
        // Print the name of the newly added animal
        System.out.println("Added a new animal with name '" + animal.getName() + "'");
    }
}

最后要實現驅動應用的主函數:

public class Main {
    public static void main (String[] args) {
        // Create the zoo to store animals
        Zoo zoo = new Zoo();
        // Register a listener to be notified when an animal is added
        zoo.registerAnimalAddedListener(new PrintNameAnimalAddedListener());
        // Add an animal notify the registered listeners
        zoo.addAnimal(new Animal("Tiger"));
    }
}

主函數只是簡單的創建了一個zoo對象,注冊了一個輸出動物name的監聽器,并新建了一個animal對象以觸發已注冊的監聽器,最后的輸出為:

Added a new animal with name 'Tiger'

新增監聽器

當監聽器重新建立并將其添加到Subject時,觀察者模式的優勢就充分顯示出來。例如,想添加一個計算動物園中動物 總數的監聽器,只需要新建一個具體的監聽器類并注冊到Zoo類即可,而無需對zoo類做任何修改。添加計數監聽器 CountingAnimalAddedListener代碼如下:

public class CountingAnimalAddedListener implements AnimalAddedListener {
    private static int animalsAddedCount = 0;
    @Override
    public void updateAnimalAdded (Animal animal) {
        // Increment the number of animals
        animalsAddedCount++;
        // Print the number of animals
        System.out.println("Total animals added: " + animalsAddedCount);
    }
}

修改后的main函數如下:

public class Main {
    public static void main (String[] args) {
        // Create the zoo to store animals
        Zoo zoo = new Zoo();
        // Register listeners to be notified when an animal is added
        zoo.registerAnimalAddedListener(new PrintNameAnimalAddedListener());
        zoo.registerAnimalAddedListener(new CountingAnimalAddedListener());
        // Add an animal notify the registered listeners
        zoo.addAnimal(new Animal("Tiger"));
        zoo.addAnimal(new Animal("Lion"));
        zoo.addAnimal(new Animal("Bear"));
    }
}

輸出結果為:

Added a new animal with name 'Tiger'
Total animals added: 1
Added a new animal with name 'Lion'
Total animals added: 2
Added a new animal with name 'Bear'
Total animals added: 3

使用者可在僅修改監聽器注冊代碼的情況下,創建任意監聽器。具有此可擴展性主要是因為Subject和觀察者接口關聯,而不是直接和ConcreteObserver關聯。只要接口不被修改,調用接口的Subject就無需修改。

匿名內部類,Lambda函數和監聽器注冊

Java8 的一大改進是增加了功能特性,如增加了lambda函數。在引進lambda函數之前,Java通過匿名內部類提供了類似的功能,這些類在很多已有的應用 中仍在使用。在觀察者模式下,隨時可以創建新的監聽器而無需創建具體觀察者類,例如,PrintNameAnimalAddedListener類可以在 main函數中用匿名內部類實現,具體實現代碼如下:

public class Main {
    public static void main (String[] args) {
        // Create the zoo to store animals
        Zoo zoo = new Zoo();
        // Register listeners to be notified when an animal is added
        zoo.registerAnimalAddedListener(new AnimalAddedListener() {
            @Override
            public void updateAnimalAdded (Animal animal) {
                // Print the name of the newly added animal
                System.out.println("Added a new animal with name '" + animal.getName() + "'");
            }
        });
        // Add an animal notify the registered listeners
        zoo.addAnimal(new Animal("Tiger"));
    }
}

類似的,lambda函數也可以用以完成此類任務:

public class Main {
    public static void main (String[] args) {
        // Create the zoo to store animals
        Zoo zoo = new Zoo();
        // Register listeners to be notified when an animal is added
        zoo.registerAnimalAddedListener(
            (animal) -> System.out.println("Added a new animal with name '" + animal.getName() + "'")
        );
        // Add an animal notify the registered listeners
        zoo.addAnimal(new Animal("Tiger"));
    }
}

需要注意的是lambda函數僅適用于監聽器接口只有一個函數的情況,這個要求雖然看起來嚴格,但實際上很多監聽器都是單一函數的,如示例中的AnimalAddedListener。如果接口有多個函數,可以選擇使用匿名內部類。

隱 式注冊創建的監聽器存在此類問題:由于對象是在注冊調用的范圍內創建的,所以不可能將引用存儲一個到具體監聽器。這意味著,通過lambda函數或者匿名 內部類注冊的監聽器不可以撤銷注冊,因為撤銷函數需要傳入已經注冊監聽器的引用。解決這個問題的一個簡單方法是在 registerAnimalAddedListener函數中返回注冊監聽器的引用。如此一來,就可以撤銷注冊用lambda函數或匿名內部類創建的監 聽器,改進后的方法代碼如下:

public AnimalAddedListener registerAnimalAddedListener (AnimalAddedListener listener) {
    // Add the listener to the list of registered listeners
    this.listeners.add(listener); 
    return listener;
}

重新設計的函數交互的客戶端代碼如下:

public class Main {
    public static void main (String[] args) {
        // Create the zoo to store animals
        Zoo zoo = new Zoo();
        // Register listeners to be notified when an animal is added
        AnimalAddedListener listener = zoo.registerAnimalAddedListener(
            (animal) -> System.out.println("Added a new animal with name '" + animal.getName() + "'")
        );
        // Add an animal notify the registered listeners
        zoo.addAnimal(new Animal("Tiger"));
        // Unregister the listener
        zoo.unregisterAnimalAddedListener(listener);
        // Add another animal, which will not print the name, since the listener
        // has been previously unregistered
        zoo.addAnimal(new Animal("Lion"));
    }
}

此時的結果輸出只有Added a new animal with name ‘Tiger’,因為在第二個animal加入之前監聽器已經撤銷了:

Added a new animal with name 'Tiger'

如果采用更復雜的解決方案,register函數也可以返回receipt類,以便unregister監聽器調用,例如:

public class AnimalAddedListenerReceipt {
    private final AnimalAddedListener listener;
    public AnimalAddedListenerReceipt (AnimalAddedListener listener) {
        this.listener = listener;
    }
    public final AnimalAddedListener getListener () {
        return this.listener;
    }
}

receipt會作為注冊函數的返回值,以及撤銷注冊函數輸入參數,此時的zoo實現如下所示:

public class ZooUsingReceipt {
    // ...Existing attributes and constructor...
    public AnimalAddedListenerReceipt registerAnimalAddedListener (AnimalAddedListener listener) {
        // Add the listener to the list of registered listeners
        this.listeners.add(listener);
        return new AnimalAddedListenerReceipt(listener);
    }
    public void unregisterAnimalAddedListener (AnimalAddedListenerReceipt receipt) {
        // Remove the listener from the list of the registered listeners
        this.listeners.remove(receipt.getListener());
    }
    // ...Existing notification method...
}

上面描述的接收實現機制允許保存信息供監聽器撤銷時調用的,也就是說如果撤銷注冊算法依賴于Subject注冊監聽器時的狀態,則此狀態將被保存,如果撤銷注冊只需要指向之前注冊監聽器的引用,這樣的話接收技術則顯得麻煩,不推薦使用。

除了特別復雜的具體監聽器,最常見的注冊監聽器的方法是通過lambda函數或通過匿名內部類注冊。當然,也有例外,那就是包含subject實現觀察者接口的類和注冊一個包含調用該引用目標的監聽器。如下面代碼所示的案例:

public class ZooContainer implements AnimalAddedListener {
    private Zoo zoo = new Zoo();
    public ZooContainer () {
        // Register this object as a listener
        this.zoo.registerAnimalAddedListener(this);
    }
    public Zoo getZoo () {
        return this.zoo;
    }
    @Override
        public void updateAnimalAdded (Animal animal) {
        System.out.println("Added animal with name '" + animal.getName() + "'");
    }
    public static void main (String[] args) {
        // Create the zoo container
        ZooContainer zooContainer = new ZooContainer();
        // Add an animal notify the innerally notified listener
        zooContainer.getZoo().addAnimal(new Animal("Tiger"));
    }
}

這種方法只適用于簡單情況而且代碼看起來不夠專業,盡管如此,它還是深受現代Java開發人員的喜愛,因此了解這個例子的工作原理很有必要。因為 ZooContainer實現了AnimalAddedListener接口,那么ZooContainer的實例(或者說對象)就可以注冊為 AnimalAddedListener。ZooContainer類中,該引用代表當前對象即ZooContainer的一個實例,所以可以被用作 AnimalAddedListener。

通常,不是要求所有的container類都實現此類功能,而且實現監聽器接口的container類只能調用Subject的注冊函數,只是簡單把該引用作為監聽器的對象傳給register函數。在接下來的章節中,將介紹多線程環境的常見問題和解決方案。

線程安全的實現

前 面章節介紹了在現代Java環境下的實現觀察者模式,雖然簡單但很完整,但這一實現忽略了一個關鍵性問題:線程安全。大多數開放的Java應用都是多線程 的,而且觀察者模式也多用于多線程或異步系統。例如,如果外部服務更新其數據庫,那么應用也會異步地收到消息,然后用觀察者模式通知內部組件更新,而不是 內部組件直接注冊監聽外部服務。

觀察者模式的線程安全主要集中在模式的主體上,因為修改注冊監聽器集合時很可能發生線程沖突,比如,一個線 程試圖添加一個新的監聽器,而另一線程又試圖添加一個新的animal對象,這將觸發對所有注冊監聽器的通知。鑒于先后順序,在已注冊的監聽器收到新增動 物的通知前,第一個線程可能已經完成也可能尚未完成新監聽器的注冊。這是一個經典的線程資源競爭案例,正是這一現象告訴開發者們需要一個機制來保證線程安 全。

這一問題的最簡單的解決方案是:所有訪問或修改注冊監聽器list的操作都須遵循Java的同步機制,比如:

public synchronized AnimalAddedListener registerAnimalAddedListener (AnimalAddedListener listener) { /*...*/ }
public synchronized void unregisterAnimalAddedListener (AnimalAddedListener listener) { /*...*/ }
public synchronized void notifyAnimalAddedListeners (Animal animal) { /*...*/ }

這樣一來,同一時刻只有一個線程可以修改或訪問已注冊的監聽器列表,可以成功地避免資源競爭問題,但是新問題又出現了,這樣的約束太過嚴格 (synchronized關鍵字和Java并發模型的更多信息,請參閱官方網頁)。通過方法同步,可以時刻觀測對監聽器list的并發訪問,注冊和撤銷 監聽器對監聽器list而言是寫操作,而通知監聽器訪問監聽器list是只讀操作。由于通過通知訪問是讀操作,因此是可以多個通知操作同時進行的。

因 此,只要沒有監聽器注冊或撤銷注冊,任意多的并發通知都可以同時執行,而不會引發對注冊的監聽器列表的資源爭奪。當然,其他情況下的資源爭奪現象存在已 久,為了解決這一問題,設計了ReadWriteLock用以分開管理讀寫操作的資源鎖定。Zoo類的線程安全ThreadSafeZoo實現代碼如下:

public class ThreadSafeZoo {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    protected final Lock readLock = readWriteLock.readLock();
    protected final Lock writeLock = readWriteLock.writeLock();
    private List<animal> animals = new ArrayList<>();
    private List<animaladdedlistener> listeners = new ArrayList<>();
    public void addAnimal (Animal animal) {
        // Add the animal to the list of animals
        this.animals.add(animal);
        // Notify the list of registered listeners
        this.notifyAnimalAddedListeners(animal);
    }
    public AnimalAddedListener registerAnimalAddedListener (AnimalAddedListener listener) {
        // Lock the list of listeners for writing
        this.writeLock.lock();
        try {
            // Add the listener to the list of registered listeners
            this.listeners.add(listener);
        }
        finally {
            // Unlock the writer lock
            this.writeLock.unlock();
        }
        return listener;
    }
    public void unregisterAnimalAddedListener (AnimalAddedListener listener) {
        // Lock the list of listeners for writing
        this.writeLock.lock();
        try {
            // Remove the listener from the list of the registered listeners
            this.listeners.remove(listener);
        }
        finally {
            // Unlock the writer lock
            this.writeLock.unlock();
        }
    }
    public void notifyAnimalAddedListeners (Animal animal) {
        // Lock the list of listeners for reading
        this.readLock.lock();
        try {
            // Notify each of the listeners in the list of registered listeners
            this.listeners.forEach(listener -> listener.updateAnimalAdded(animal));
        }
        finally {
            // Unlock the reader lock
            this.readLock.unlock();
        }
    }
}

通過這樣部署,Subject的實現能確保線程安全并且多個線程可以同時發布通知。但盡管如此,依舊存在兩個不容忽略的資源競爭問題:

  1. 對每個監聽器的并發訪問。多個線程可以同時通知監聽器要新增動物了,這意味著一個監聽器可能會同時被多個線程同時調用。

  2. 對animal list的并發訪問。多個線程可能會同時向animal list添加對象,如果通知的先后順序存在影響,那就可能導致資源競爭,這就需要一個并發操作處理機制來避免這一問題。如果注冊的監聽器列表在收到通知添 加animal2后,又收到通知添加animal1,此時就會產生資源競爭。但是如果animal1和animal2的添加由不同的線程執行,也是有可能 在animal2前完成對animal1添加操作,具體來說就是線程1在通知監聽器前添加animal1并鎖定模塊,線程2添加animal2并通知監聽 器,然后線程1通知監聽器animal1已經添加。雖然在不考慮先后順序時,可以忽略資源競爭,但問題是真實存在的。

對監聽器的并發訪問

并發訪問監聽器可以通過保證監聽器的線程安全來實現。秉承著類的“責任自負”精神,監聽器有“義 務”確保自身的線程安全。例如,對于前面計數的監聽器,多線程的遞增或遞減動物數量可能導致線程安全問題,要避免這一問題,動物數的計算必須是原子操作 (原子變量或方法同步),具體解決代碼如下:

public class ThreadSafeCountingAnimalAddedListener implements AnimalAddedListener {
    private static AtomicLong animalsAddedCount = new AtomicLong(0);
    @Override
    public void updateAnimalAdded (Animal animal) {
        // Increment the number of animals
        animalsAddedCount.incrementAndGet();
        // Print the number of animals
        System.out.println("Total animals added: " + animalsAddedCount);
    }
}

方法同步解決方案代碼如下:

public class CountingAnimalAddedListener implements AnimalAddedListener {
    private static int animalsAddedCount = 0;
    @Override
    public synchronized void updateAnimalAdded (Animal animal) {
        // Increment the number of animals
        animalsAddedCount++;
        // Print the number of animals
        System.out.println("Total animals added: " + animalsAddedCount);
    }
}

要強調的是監聽器應該保證自身的線程安全,subject需要理解監聽器的內部邏輯,而不是簡單確保對監聽器的訪問和修改的線程安全。否則,如果多 個subject共用同一個監聽器,那每個subject類都要重寫一遍線程安全的代碼,顯然這樣的代碼不夠簡潔,因此需要在監聽器類內實現線程安全。

監聽器的有序通知

當 要求監聽器有序執行時,讀寫鎖就不能滿足需求了,而需要引入一個新的機制,可以保證notify函數的調用順序和animal添加到zoo的順序一致。有 人嘗試過用方法同步來實現,然而根據Oracle文檔中的方法同步介紹,可知方法同步并不提供操作執行的順序管理。它只是保證原子操作,也就是說操作不會 被打斷,并不能保證先來先執行(FIFO)的線程順序。ReentrantReadWriteLock可以實現這樣的執行順序,代碼如下:

public class OrderedThreadSafeZoo {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    protected final Lock readLock = readWriteLock.readLock();
    protected final Lock writeLock = readWriteLock.writeLock();
    private List<animal> animals = new ArrayList<>();
    private List<animaladdedlistener> listeners = new ArrayList<>();
    public void addAnimal (Animal animal) {
        // Add the animal to the list of animals
        this.animals.add(animal);
        // Notify the list of registered listeners
        this.notifyAnimalAddedListeners(animal);
    }
    public AnimalAddedListener registerAnimalAddedListener (AnimalAddedListener listener) {
        // Lock the list of listeners for writing
        this.writeLock.lock();
        try {
            // Add the listener to the list of registered listeners
            this.listeners.add(listener);
        }
        finally {
            // Unlock the writer lock
            this.writeLock.unlock();
        }
        return listener;
    }
    public void unregisterAnimalAddedListener (AnimalAddedListener listener) {
        // Lock the list of listeners for writing
        this.writeLock.lock();
        try {
            // Remove the listener from the list of the registered listeners
            this.listeners.remove(listener);
        }
        finally {
            // Unlock the writer lock
            this.writeLock.unlock();
        }
    }
    public void notifyAnimalAddedListeners (Animal animal) {
        // Lock the list of listeners for reading
        this.readLock.lock();
        try {
            // Notify each of the listeners in the list of registered listeners
            this.listeners.forEach(listener -> listener.updateAnimalAdded(animal));
        }
        finally {
            // Unlock the reader lock
            this.readLock.unlock();
        }
    }
}

這樣的實現方式,register, unregister和notify函數將按照先進先出(FIFO)的順序獲得讀寫鎖權限。例如,線程1注冊一個監聽器,線程2在開始執行注冊操作后試圖 通知已注冊的監聽器,線程3在線程2等待只讀鎖的時候也試圖通知已注冊的監聽器,采用fair-ordering方式,線程1先完成注冊操作,然后線程2 可以通知監聽器,最后線程3通知監聽器。這樣保證了action的執行順序和開始順序一致。

如果采用方法同步,雖然線程2先排隊等待占用資 源,線程3仍可能比線程2先獲得資源鎖,而且不能保證線程2比線程3先通知監聽器。問題的關鍵所在:fair-ordering方式可以保證線程按照申請 資源的順序執行。讀寫鎖的順序機制很復雜,應參照ReentrantReadWriteLock的官方文檔以確保鎖的邏輯足夠解決問題。

截止目前實現了線程安全,在接下來的章節中將介紹提取主題的邏輯并將其mixin類封裝為可重復代碼單元的方式優缺點。

主題邏輯封裝到Mixin類

把 上述的觀察者模式設計實現封裝到目標的mixin類中很具吸引力。通常來說,觀察者模式中的觀察者包含已注冊的監聽器的集合;負責注冊新的監聽器的 register函數;負責撤銷注冊的unregister函數和負責通知監聽器的notify函數。對于上述的動物園的例子,zoo類除動物列表是問題 所需外,其他所有操作都是為了實現主題的邏輯。

Mixin類的案例如下所示,需要說明的是為使代碼更為簡潔,此處去掉關于線程安全的代碼:

public abstract class ObservableSubjectMixin<listenertype> {
    private List<listenertype> listeners = new ArrayList<>();
    public ListenerType registerListener (ListenerType listener) {
        // Add the listener to the list of registered listeners
        this.listeners.add(listener);
        return listener;
    }
    public void unregisterAnimalAddedListener (ListenerType listener) {
        // Remove the listener from the list of the registered listeners
        this.listeners.remove(listener);
    }
    public void notifyListeners (Consumer<!--? super ListenerType--> algorithm) {
        // Execute some function on each of the listeners
        this.listeners.forEach(algorithm);
    }
}

正因為沒有提供正在注冊的監聽器類型的接口信息,不能直接通知某個特定的監聽器,所以正需要保證通知功能的通用性,允許客戶端添加一些功能,如接受泛型參數類型的參數匹配,以適用于每個監聽器,具體實現代碼如下:

public class ZooUsingMixin extends ObservableSubjectMixin<animaladdedlistener> {
    private List<animal> animals = new ArrayList<>();
    public void addAnimal (Animal animal) {
        // Add the animal to the list of animals
        this.animals.add(animal);
        // Notify the list of registered listeners
        this.notifyListeners((listener) -> listener.updateAnimalAdded(animal));
    }
}

Mixin類技術的最大優勢是把觀察者模式的Subject封裝到一個可重復調用的類中,而不是在每個subject類中都重復寫這些邏輯。此外,這一方法使得zoo類的實現更為簡潔,只需要存儲動物信息,而不用再考慮如何存儲和通知監聽器。

然 而,使用mixin類并非只有優點。比如,如果要存儲多個類型的監聽器怎么辦?例如,還需要存儲監聽器類型AnimalRemovedListener。 mixin類是抽象類,Java中不能同時繼承多個抽象類,而且mixin類不能改用接口實現,這是因為接口不包含state,而觀察者模式中state 需要用來保存已經注冊的監聽器列表。

其中的一個解決方案是創建一個動物增加和減少時都會通知的監聽器類型ZooListener,代碼如下所示:

public interface ZooListener {
    public void onAnimalAdded (Animal animal);
    public void onAnimalRemoved (Animal animal);
}

這樣就可以使用該接口實現利用一個監聽器類型對zoo狀態各種變化的監聽了:

public class ZooUsingMixin extends ObservableSubjectMixin<zoolistener> {
    private List<animal> animals = new ArrayList<>();
    public void addAnimal (Animal animal) {
        // Add the animal to the list of animals
        this.animals.add(animal);
        // Notify the list of registered listeners
        this.notifyListeners((listener) -> listener.onAnimalAdded(animal));
    }
    public void removeAnimal (Animal animal) {
        // Remove the animal from the list of animals
        this.animals.remove(animal);
        // Notify the list of registered listeners
        this.notifyListeners((listener) -> listener.onAnimalRemoved(animal));
    }
}

將多個監聽器類型合并到一個監聽器接口中確實解決了上面提到的問題,但仍舊存在不足之處,接下來的章節會詳細討論。

Multi-Method監聽器和適配器

在 上述方法,監聽器的接口中實現的包含太多函數,接口就過于冗長,例如,Swing MouseListener就包含5個必要的函數。盡管可能只會用到其中一個,但是只要用到鼠標點擊事件就必須要添加這5個函數,更多可能是用空函數體來 實現剩下的函數,這無疑會給代碼帶來不必要的混亂。

其中一種解決方案是創建適配器(概念來自GoF提出的適配器模式),適配器中以抽象函數 的形式實現監聽器接口的操作,供具體監聽器類繼承。這樣一來,具體監聽器類就可以選擇其需要的函數,對adapter不需要的函數采用默認操作即可。例如 上面例子中的ZooListener類,創建ZooAdapter(Adapter的命名規則與監聽器一致,只需要把類名中的Listener改為 Adapter即可),代碼如下:

public class ZooAdapter implements ZooListener {
    @Override
    public void onAnimalAdded (Animal animal) {}
    @Override
    public void onAnimalRemoved (Animal animal) {}
}

乍一看,這個適配器類微不足道,然而它所帶來的便利卻是不可小覷的。比如對于下面的具體類,只需選擇對其實現有用的函數即可:

public class NamePrinterZooAdapter extends ZooAdapter {
    @Override
    public void onAnimalAdded (Animal animal) {
        // Print the name of the animal that was added
        System.out.println("Added animal named " + animal.getName());
    }
}

有兩種替代方案同樣可以實現適配器類的功能:一是使用默認函數;二是把監聽器接口和適配器類合并到一個具體類中。默認函數是Java8新提出的,在接口中允許開發者提供默認(防御)的實現方法。

Java 庫的這一更新主要是方便開發者在不改變老版本代碼的情況下,實現程序擴展,因此應該慎用這個方法。部分開發者多次使用后,會感覺這樣寫的代碼不夠專業,而 又有開發者認為這是Java8的特色,不管怎樣,需要明白這個技術提出的初衷是什么,再結合具體問題決定是否要用。使用默認函數實現的 ZooListener接口代碼如下示:

public interface ZooListener {
    default public void onAnimalAdded (Animal animal) {}
    default public void onAnimalRemoved (Animal animal) {}
}

通過使用默認函數,實現該接口的具體類,無需在接口中實現全部函數,而是選擇性實現所需函數。雖然這是接口膨脹問題一個較為簡潔的解決方案,開發者在使用時還應多加注意。

第二種方案是簡化觀察者模式,省略了監聽器接口,而是用具體類實現監聽器的功能。比如ZooListener接口就變成了下面這樣:

public class ZooListener {
    public void onAnimalAdded (Animal animal) {}
    public void onAnimalRemoved (Animal animal) {}
}

這一方案簡化了觀察者模式的層次結構,但它并非適用于所有情況,因為如果把監聽器接口合并到具體類中,具體監聽器就不可以實現多個監聽接口了。例 如,如果AnimalAddedListener和AnimalRemovedListener接口寫在同一個具體類中,那么單獨一個具體監聽器就不可以 同時實現這兩個接口了。此外,監聽器接口的意圖比具體類更顯而易見,很顯然前者就是為其他類提供接口,但后者就并非那么明顯了。

如果沒有合適的文檔說明,開發者并不會知道已經有一個類扮演著接口的角色,實現了其對應的所有函數。此外,類名不包含adapter,因為類并不適配于某一個接口,因此類名并沒有特別暗示此意圖。綜上所述,特定問題需要選擇特定的方法,并沒有哪個方法是萬能的。

在 開始下一章前,需要特別提一下,適配器在觀察模式中很常見,尤其是在老版本的Java代碼中。Swing API正是以適配器為基礎實現的,正如很多老應用在Java5和Java6中的觀察者模式中所使用的那樣。zoo案例中的監聽器或許并不需要適配器,但需 要了解適配器提出的目的以及其應用,因為我們可以在現有的代碼中對其進行使用。下面的章節,將會介紹時間復雜的監聽器,該類監聽器可能會執行耗時的運算或 進行異步調用,不能立即給出返回值。

Complex & Blocking監聽器

關于觀察者模式的一個假設是: 執行一個函數時,一系列監聽器會被調用,但假定這一過程對調用者而言是完全透明的。例如,客戶端代碼在Zoo中添加animal時,在返回添加成功之前, 并不知道會調用一系列監聽器。如果監聽器的執行需要時間較長(其時間受監聽器的數量、每個監聽器執行時間影響),那么客戶端代碼將會感知這一簡單增加動物 操作的時間副作用。

本文不能面面俱到的討論這個話題,下面幾條是開發者調用復雜的監聽器時應該注意的事項:

  1. 監聽器啟動新線程。新線程啟動后,在新線程中執行監聽器邏輯的同時,返回監聽器函數的處理結果,并運行其他監聽器執行。

2. Subject啟動新線程。與傳統的線性迭代已注冊的監聽器列表不同,Subject的notify函數重啟一個新的線程,然后在新線程中迭代監聽器列 表。這樣使得notify函數在執行其他監聽器操作的同時可以輸出其返回值。需要注意的是需要一個線程安全機制來確保監聽器列表不會進行并發修改。

3. 隊列化監聽器調用并采用一組線程執行監聽功能。將監聽器操作封裝在一些函數中并隊列化這些函數,而非簡單的迭代調用監聽器列表。這些監聽器存儲到隊列中 后,線程就可以從隊列中彈出單個元素并執行其監聽邏輯。這類似于生產者-消費者問題,notify過程產生可執行函數隊列,然后線程依次從隊列中取出并執 行這些函數,函數需要存儲被創建的時間而非執行的時間供監聽器函數調用。例如,監聽器被調用時創建的函數,那么該函數就需要存儲該時間點,這一功能類似于 Java中的如下操作:

public class AnimalAddedFunctor {
    private final AnimalAddedListener listener;
    private final Animal parameter;
    public AnimalAddedFunctor (AnimalAddedListener listener, Animal parameter) {
        this.listener = listener;
        this.parameter = parameter;
    }
    public void execute () {
        // Execute the listener with the parameter provided during creation
        this.listener.updateAnimalAdded(this.parameter);
    }
}

函數創建并保存在隊列中,可以隨時調用,這樣一來就無需在遍歷監聽器列表時立即執行其對應操作了。一旦每個激活監聽器的函數都壓入隊列中,“消費者 線程”就會給客戶端代碼返回操作權。之后某個時間點“消費者線程”將會執行這些函數,就像在監聽器被notify函數激活時執行一樣。這項技術在其他語言 中被叫作參數綁定,剛好適合上面的例子,技術的實質是保存監聽器的參數,execute()函數再直接調用。如果監聽器接收多個參數,處理方法也類似。

需 要注意的是如果要保存監聽器的執行順序,則需要引入綜合排序機制。方案一中,監聽器按照正常的順序激活新線程,這樣可以確保監聽器按照注冊的順序執行。方 案二中,隊列支持排序,其中的函數會按照進入隊列的順序執行。簡單來說就是,開發者需要重視監聽器多線程執行的復雜程度,加以小心處理以確保實現所需的功 能。

結束語

觀察者模式在1994年被寫進書中以前,就已經是主流的軟件設計模式了,為軟件設計中經常出現的問題提供了很 多令人滿意的解決方案。Java一直是使用該模式的引領者,在其標準庫中封裝了這一模式,但是鑒于Java更新到了版本8,十分有必要重新考查經典模式在 其中的使用。隨著lambda表達式和其他新結構的出現,這一“古老的”模式又有了新的生機。無論是處理舊程序還是使用這一歷史悠久的方法解決新問題,尤 其對經驗豐富的Java開發者來說,觀察者模式都是開發者的主要工具。

原文鏈接:

譯者:王鵬,OneAPM工程師

順帶提個好消息,


標簽:JavaMyEclipse

本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn


為你推薦

  • 推薦視頻
  • 推薦活動
  • 推薦產品
  • 推薦文章
  • 慧都慧問
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
主站蜘蛛池模板: 国产在线21 | 国产成年人在线 | 欧美性爱第8页 | 国产精品酒店 | 精品动漫一区 | 自由偷拍综合 | 日韩精品亚洲人成在线 | 精品国模吧| 日韩在线视频点击观看 | 午夜色色影院 | 九一福利 | 国产成人片 | 丰满多毛的大陰户特写 | 日韩综合在线视频 | 日韩在线视频观看 | 无码影视在线 | 国产三级播放 | 日韩一区在线播放 | 福利视频导航大全 | 国产又爽又黄A片 | 一区二区不卡 | 成人福利网站在线观看 | 国产高潮白浆喷水 | 老湿机在线免费观看 | 成人精品性色一二三区 | 日韩无码成人 | 日韩高清电影网 | 乱伦日屄视频 | 国产h视频在线观看 | 国产精品女主播 | 久久综合888 | 亚洲AV一卡| 国产精品无| 日韩欧美制服另类 | 日韩午夜福利 | 操逼操123 | 涩涩在线观看视频 | 国产一级黄片 | av一卡二卡 | 日韩欧美精品一 | 丨97丨另类丰满人妖 | 国产91传媒| 日本A片在线观看 | 日韩中文字幕在线不卡 | 日韩中文字幕在线有码 | 亚州精品无码毛片 | 国产精久久久 | 成人免费观看 | 午夜天堂视频 | 国产9自拍 | 岛国一级a | 成人片a免看 | 日韩欧美丝袜一区二区 | 成人三级在线 | 国产三级电影在线观看 | 日韩理论午夜 | 四虎最新网站 | 女同另类之国产女同 | 成人性综合网 | 欧美网站色 | 丁香五月亚洲婷婷 | 国产福利姬 | 日韩精品第2页 | 国产大学生一区 | 日韩成人视频在线 | 日韩在线免费看 | 三级在线成人 | 日韩性爱黄页网 | 女人脱精光按摩AA片 | 污视频网址在线观看 | 福利姬视频在线看 | 日韩伦理片在线观看 | 午夜福利导航视频 | 天堂新在线 | 午夜伦理在线观看 | 久久不卡免费视频 | 国产又黄又猛又粗又爽 | 成人欧美一区二区三 | 性爱网站在线看 | 日韩欧美亚洲激情 | 麻豆网页 | 日韩在线精品视频播放 | 国产无码观看 | 成人精品第 | 三级精品免费影视 | 午夜成人福利网 | 91玉足丝袜| 老湿影院在线观看视频 | 国产不卡高清 | 成人三级小视频 | 国产h片在线观 | 91资源站 | 成人国产极品在线视频 | 日韩综合精品第18页 | 国产高潮白浆喷水男男 | 成年女人av | 深夜福利国产小视频 | 黄色av网站免费观看 | 精品日韩一区二区三区 | 国产女人喷液 | 日韩大片在线观看 | 中文字幕之久久 | 强奸乱伦视频网 | 国产国产人 | 福利姬视频观看 | 狼友福利视频 | 日韩亚洲欧亚自 | 国产又粗又黄又爽视频 | 激情五月黄| 无码高清一区二区 | 国产乱码精品 | 日韩三级精品 | 日韩一区欧美精品 | 又粗又黄A片三男一女 | 日韩风间由 | 午夜视频软件 | 97在线观看视频 | 国产视频观看 | 一卡二卡AV| 极品白嫩虎白女视频 | 国产经典三级手机观看 | 97人人操人人干 | 日本中文无码字幕 | 国产一级内射视频 | 国产激情一区 | 中文字幕久久在线观看 | 国产成人性爱在线观看 | 成人美女视频在 | 日韩精品a人 | 久久国产精品一区二区 | 成人午夜免费看 | 亚洲动漫精品 | 国产三级无码在线 | 超碰成人免费电影 | 国产色情在线观看 | 欧美视频在线播放 | 欧美91视频 | 日韩爱爱| 成人黃色一級片 | 日韩视频免费在线 | 午夜无码在线观看视频 | 国产成人精品在线观看 | 国产伦理三级 | 国产经典剧情一曲二曲 | 玖草在线免费观看 | 三级毛片网 | 日韩精品射 | 日韩伦理片 | 成人午夜电影在线 | 日韩午夜福利片在线观 | 国产精品传媒在线观看 | 日韩欧美一区免费极品 | 日韩无码中文字幕 | 日韩性爱黄页网 | 国产免费一 | 成人性生交大 | 激情文学第一页 | 亚洲人网av| 九九黄色| 中国国产精品 | 国产免国产免费 | 国产一区在线观看视频 | 成人dvd碟片 | 日韩中文高清在线 | 黄wwwwww| 国产资源精品 | 欧美成人性爱视频 | 国产美女高潮 | www亚洲精品 | 91视频一区二区三区 | 色情性黄片免费视频 | 日韩精品淫途 | 女人喷水视频 | 日韩精品高清自在线 | 夜福利视频| 国产系列在线 | 无码不卡在线看 | 91系列| 欧美日韩国产在线 | 精品免费囯产一区 | 91淫浮| 日本不卡一区 | 狼友视频国产精品 | 91一区二区三区 | 国产厕所视频在线播放 | 亚洲色图1| 精品久久影院 | 午夜免费福利视频 | 另类天堂| 91探花视频 | 九一看片 | 午夜成人无码电影 | 三级视频院 | 日韩高清影院 | 最新国产三级在线观看 | 日韩影院在线观看 | 日韩欧美在线中文字幕 | 日韩中文字幕在线 | 91午夜 | 三级片网址大全 | 国模冰莲私拍极品肥美 | 日韩伦理在线看网站 | 日韩欧美国产一区二区 | 另类激情文学 | 日韩在线一区二区三区 | 国产女同一区 | 国产精品国色综合久久 | 玖玖爱中文字幕 | 国产人人看 | av天堂黄色 | 国产人妖精品视频 | 日韩色情| 高潮流白浆视频 | 日韩电影资源 | 夜夜视频免费看 | 丁香婷婷五月 | 日韩在线视频专区免费 | 91亚洲| 日韩成人精品在线观看 | 欧美在线视频91 | 欧美ab| av加勒比| 日韩国产欧美精品综 | 男同h片| 日韩爱爱| 国产自线再拍 | 热九九九久久 | 日韩精品国产高清 | 午夜福利视频网 | 国产精品a无线 | 日韩精品亚洲一区 | 性爱自拍第一区 | 欧美黄色网址 | 欧美极品一区 | 午夜无码福利在线观看 | 午夜在线直播 | 欧美专区在线 | 国产久久一区 | 日韩经典欧 | 岛国午夜视频 | 国产AV淫乱兄妹 | 日韩欧美国产偷亚洲清 | 深夜福利网址在线观看 | 国产精品视频二 | 日韩一区二区欧美一区 | 国产在线三级视频观看 | 国产成人在线免费观看 | 日本A区| 成人免费午夜视频 | 正在播放城中村嫖妓 | 日韩欧美另类一区在线 | 午夜成人av在线观看 | 久久九九国产 | 日韩一区欧美精品 | 日韩欧美国产偷亚洲清 | 亚洲AV国产精品 | 成人艳情一二三区 | 成人福利导航大全在线 | 日韩视频一区二区 | 日韩国品一 | 日韩免va | 午夜影视剧场 | 国产精品成人片 | 日韩亚洲国产中文永久 | 成人免费片 | 国产呦合第一系 | 中国操逼图 | 偷拍自拍在线免费观看 | 中国三级片在线观看 | 国产精品无码无码 | 国产乱伦大全 | 天堂在线视频 | 婷婷激情综合 | 国产人妖在线观看 | 三级全黄三级bd | 另类变态人妖 | 国产97视| 日韩一三区国产福利 | 日韩欧美偷拍精品一区 | 日韩国产精品影院 | 国产a国产片 | 99自拍视频在线观看 | 欧美精品在线视频 | 超碰在线视97 | 福利导航网址 | 可以看的三级网站 | 综合久久中文 | 亚洲啊v| 免费成人黄片 | 成人片资源 | 成人资源在线观看 | 日韩欧美影视 | 日韩a级片电影 | 日本人妻中文字幕 | 日韩精品三级一区二区 | 日韩欧美亚洲中 | 美女视频毛片 | 日韩国产精品有吗在线 | 成人免费亚洲视频 | 91在线观看免费高清 | 高清无码专区 | 俄罗斯无码 | 激情图片成人小说 | 天美传奇传媒mv观看 | 上床啪啪啪在线网站 | 国产v亚洲v天堂无 | 成人快插 | 欧美日韩精品一区二 | 日韩在线观看精品 | 国产69精品久 | 国产亚洲高清在线 | 日韩中文字幕在线视频 | 日韩精品秘 在线观看 | 麻豆视频第一三区 | 国产三级国产在线观看 | 深夜福利一区 | 午夜福利在线看 | 日韩不卡一二三 | 国产免国产免费 | 日韩一区免费观看 | 成人午夜在线视频 | 97超碰成人在线 | 福利在线视频 | 草莓视频网站成人18 | 东京热HEYZO无码 | 成人三级在哪里看 | 深夜福利在线免费观看 | 亚洲人成一区 | 国产自拍 | 无码高清不卡在线 | 国产爆乳美女娇喘呻吟 | 欧美多人性爱视频 | 男人黄色天堂 | 国产福利一区二区三区 | 在线黄色AV网站 | 国产精品美乳在线观看 | 91制片国产自 | 日韩性视频在线播 | 麻豆视频传媒入口 | 无码不卡久久久久 | 91香蕉软件| 日韩精品免费看 | 免费一级毛片中文 | 老湿机网站在线观看 | 中国免费三级片 | 日韩高清精品视频在线 | 午夜福利视频网址 | 国产欧美一区二区 | 福利小视频网站 | 国产凹凸在线 | 成人免费在线观看视频 | 日韩欧美网址 | 日韩国产综合 | 在线视频天堂 | 国产全肉乱妇杂乱视频 | 做爱在线免费观看网站 | 天天日天天干天天日 | 国产成人麻豆免费观看 | 天堂…在线最新版资源 | 日韩视频在线观看1区 | 国产乱人| 尤物网站在线 | 日韩大乳视频中文字幕 | 东京热不卡 | 日韩有码在线视频 | 足交网站国产 | 国产中文字幕2 | 三级伦理日韩在线观看 | 国产美女口爆 | 成人免费视频观看 | 成人福利在线视频 | 91视频盛宴 | 激情文学第一页 | 福利视频网址导航大全 | 日韩精品久爱 | 日韩电影新片 | 久久AV不卡 | 日韩精品视频中文 | 视频列表--日韩 | 九九综合色 | 日韩欧美一区二区在线 | 天天干天天日天天操 | 涩涩视频网站 | 国产又粗又大又黄 | 欧美在线成人网站 | 久久精品只有这里有 | 宅福利导航 | 无码免费在线不卡 | 亚洲精品福利 | 国产玉足在线观看 | 午夜性理论 | 性久久影院 | 日韩福利局二区视频 | 午夜成人A| 日韩欧美理 | 欧美成人免费在线视频 | 日本一区不卡 | 城中村嫖妓视频 | 国产在线极品 | AV日韩精品| 日韩视频免费播放 | 国产传媒 | 五月丁香影院 | 久操精品在线 | 国产理论片在线观看 | 深夜福利视频一区二区 | 成人蜜桃视频在线观看 | 三级黄特色 | 污视频网址在线观看 | 在线无码小电影 | 色五月激情综合网 | 国产在线不卡 | 国产大片在线观看 | 午夜成人影视网 | 成人动漫手机在线 | 精品女同一区二区 | 日韩午夜在线 | 欧美日韩一区二区精品 | 成人中文在线电影网 | 日韩欧美国产精品一区 | 国产情侣露脸 | 日韩69| 都市激情综合 | 男人的天堂在线 | www.黃色| 日韩午夜在线视频 | www.深夜视频| 三级全黄的 | 精品天堂网 | 一区二区三区毛片 | 视频一区三区 | 国产熟女麻豆 | 国内揄拍国内精品 | 中文日韩伦理 | 国产福利视频导航 | 日韩另类视频 | 成人羞羞 | 色情婷婷 | 三级免费| 男女午夜爽爽爽 | 成人午夜在线 | 国产精品2区| 亚洲三级黄色 | 国产网站无码 | 国产屁屁 | 成人午夜被窝福利 | 亚洲高清不卡 | 日韩不卡在线观 | 狼友福利视频 | 日韩伦理片免费 | 日韩一区免费观看 | 日韩色图视频 | 国产三级视频在线 | 日本免费不卡一区 | 日韩在线观看三区 | 在线观看三级网站 | A级毛片免费看 | 日韩免费v片在线观看 | 午夜男女爽爽爽 | 国产传媒视频网站 | 午夜成人影视频道 | 国产ts视频0 | 日韩新片快播网 | 日韩激情三区 | 日韩精品秘 在线观看 | 麻豆蜜桃 | 玖玖玖玖在线 | 亚洲精品国产成人 | 激情网综合 | 在线播放的黄色网址 | 成人精品妖 | 日韩精品新网在线视频 | 成人看片在线 | 人人艹97 | 日韩在线高清 | 日韩欧美在线综合 | 狠狠干狠狠插 | 中文字幕精品日本A∨ | 日韩欧美国产一级 | 极品尤物在线 | 成人午夜免费观看 | 日韩美女精品 | 天天干天天操天天射 | 91视频免 | 福利狼视频 | 福利影院在线播放 | 日韩专区亚洲国产 | 三级黄色毛片视频网站 | 日韩中文字幕新视频 | 国产做A∨在线 | 强奸乱伦小视频 | 国产l精品国产亚洲 | 日韩免费一区二区三区 | 欧美在线视频一区 | 国产精品成人无码免费 | 日韩精品免费一区二区 | 日韩在线精品一二三区 | 精品午夜| 成人午夜福利免费视频 | 成年人深夜福利 | 拍偷第一页 | 日韩丝袜视频一区二区 | 欧美精品一 | 超碰超国产 | 黄色一级免费观看 | 国产精品久久久久不卡 | 日韩电影欧美 | 国产又粗又黄视频 | 午夜视频福利群 | 91最新在线 | 日韩欧美国产岛国精品 | 91网址| 福利社区导航 | 另类国产在线 | 国产精品不卡网 | 国产又大又粗又黄 | 成人国产不卡 | 日韩大片在线播放 | 午夜成人视频免费观看 | 成人午夜看片在线观看 | 国产乱理片在 | 国产经典三级 | 成人香蕉网 | 人人干人人摸 | 91影视在线| 日韩高清中文字幕免费 | 成人免费毛片片v | 日韩电影天堂网 | www.日本色色| 国产精品6 | 午夜日韩视频0 | 婷婷五月天综合网 | 日韩欧美中文字 | 口爆深喉| 日本精品人妻 | 日韩城人视频 | 婷婷丁香五月六月 | 亚洲美女爱爱 | 97就去色 | 日韩精品不卡 | 成人免费男女视频网 | 熟女丰满多毛大陰户 | 国产精品成人v | 天天狠狠操 | 国产日韩精品一 | 深夜福利视频在线观看 | 成人毛片在线播放免费 | 成人精品福利午夜无码 | 国产午夜小视频 | 强奸乱伦视频网址 | 日韩特级 | 偷拍第1页| 韩日成人影院 | 色五月激情综合 | 中文字幕人 | www.美女黄 | 在线国产三级 | 尤物视频在线看 | 国产人妻在线 | 成人羞羞网站入口 | 丰满的熟妇岳免费 | 福利一区二区 | 午夜成人精品视频在线 | 深夜福利无码视频 | 午夜福利电影网站 | 欧美缴情 | 激情另类文学 | 三男玩一女三A片 | 日韩电影在线观看免费 | 成人精品福利午夜无码 | 在线观看成人午夜视频 | 日韩精品区 | 日韩欧美亚洲动漫综合 | 国产不卡在线播放 | 人人超碰人人超碰 | 中文字幕日本网站 | 亚洲最新AV网站 | 91国内精品| 玖操视频在线 | 成人羞羞无遮 | 国产又黄又大 | 日韩在线观看视频网站 | 久久深夜福利 | 成人精品午夜视频 | 丝袜中文在线 | 深夜福利免费视频 | 精品国模吧 | 深夜福利视频网址 | 成人免费三级 | 三级成人视频在线观看 | 欧美精品日韩一区二区 | 麻豆传媒视频在线观看 | 国产日产欧产精 | 涩涩视频网站在线观看 | 亚洲人成www | www.日韩一区 | 性久久久久久 | 国产中文第一页 | 午夜成人AV在线播放 | 欧美日韩国产一区 | 成人信息集中地日韩 | 欧美国产精品一区二区 | 国产又大又黄 | 国产亚洲A片无码导航 | 成人h动漫精品一区 | 国产精品美脚玉 | 在线视频福利导航 | 美女被干网站 | 精品久久娱乐 | 亚洲码在线 | 国产女主播一区二区 | 欧美性爱大乱交 | 尤物视频免费在线观看 | 日韩欧美aⅴ综合网站 | 午夜手机在线视频 | 熟女毛茸茸 | 成人午夜婬片免费观看 | 另类变态人妖 | 国产又爽又粗又猛又色 | 日韩精品视频二区 | 亚洲国产一 | 日韩精品视频在线看 | 国产h在线播放 | 四房激情网 | 成人爽a毛片免费 | 日韩国产精品乱码 | 日韩高清无码免费观看 | 日韩动漫一区二 | 日日夜夜视频网 | 国产av网 | 日韩在线视频一区国产 | 岛国av在线 | 日韩在线大片 | 日韩欧美亚洲国产伊人 | 五月婷婷丁香六月 | 成人午夜高清无码 | 成人精品日韩亚洲专区 | 国产成人三级在线观看 | 日韩欧美精品一区二区 | 午夜视频在线观看网站 | 91自拍资源| 99中文字幕在线播放 | 日产三级在线观看 | 国产永久免费无 | 岛国av免费 | AV日韩精品 | 97超碰大香蕉 | 黄色三级片毛片网站 | 三级免费成人 | 午夜福利网站在线观看 | 高清無碼麻豆 | 玖玖精品网| 日韩午夜大片 | 日韩成人深夜在 | 成人免费公开视频 | 狼友永久视频 | 日本wwwxxx免费 | 国产乱对白精彩 | 老A成人无码影院 | A级成人毛片免费网站 | 中文字幕精品视频在线 | 熟妇熟女乱 | 成人午夜短视频 | 官方福利视频导航 | 午夜成人精品不卡影院 | 日韩在线精品蜜柚影院 | 欧美三区四区 | 三级亚洲欧美日本 | 国产第一区 | 日韩欧美永久中文 | 日韩在线不卡免费视频 | 日韩欧美理论在线观 | 日韩欧美国产一区呦呦 | 天天爽夜夜爽 | 日韩二级片0 | 97电影院| 三极网站 | 永久免费A级毛片 | 日韩精品二区三区 | 图片区小说区亚洲 | 国产精品高清 | 深夜福利影院在线观看 | 成人影院伦理电影 | 国产性爱在线免费观看 | 日韩欧美亚洲一区 | 成人涩涩小片视频 | 欧美日韩国产二区 | 国产经典三级 | 日韩精品在线一区二区 | 日韩视频欧美在线 | 国产亚洲AV | 国产ae| 午夜私人影院 | 日韩视频第二页 | 成人亚洲欧美日韩 | 九九九精品 | 国产主播喷 | 日韩在线人成电影大全 | 国产一精品 | 一区二区在线免费视频 | 91在线观 | 自拍在线视频 | 尤物视频网址 | 午夜福利视频 | 足交在线播放 | 日韩一区二区三区网址 | 成人午夜视 | 国产福利在线播放 | 日韩成人野外在线观看 | 欧美性爱第5页 | 成人无码A级毛片 | 国产在线不卡0 | 国产91丝 | 国产第113页 | 在线观看亚洲国产精品 | 黄色三级免费网址 | 东京热力无码 | 日韩喷水视频 | 国产性爱免费观看 | 福利导航入口 | 国产成人麻豆免费观看 | 蜜桃传媒网 | 91熟女网 | 日韩专区不卡一区 | 欧美一区视频在线 | 日韩天天精品综合 | A级片一区二区 | 日本不卡区 | 91色站| 午夜福利免费院 | 天堂网毛片 | 三级视频无码 | 图片区视频区小说区 | 丁香五月在线视频 | 日韩免费影院 | 极品精品 | 国产盗摄| 激情偷乱视频—区二区 | 日韩理论片电影 | 日韩欧美一二三区 | 午夜色色男| 成人十八影院在线观看 | 亚洲日夲三级 | 成人午夜免费观看一区 | 日韩欧美国产传媒 | 国产秘久久一区二区 | 三级网站在线播放 | 日韩一级免费免费视频 | 国产精品wwww| 永久免费A级毛片 | www.97超碰在线 | 国产原创尤物在线观看 | 成人欧美片 | 婷婷五月深爱激情网 | 国产精品成人国产 | 国产性色自拍网 | 欧美1区| 日韩丝袜高跟福利 | 97人人草| 国产va免费精品观看 | 国产又大又黄的视频 | 国产三级电影院 | 99自拍视频在线观看 | 日韩激情合集 | 玖草视频在线 | 午夜成年人网站 | 日韩亚洲欧美专区 | 国产xx在线观看 | www三级网站 | 精品女同 | 天堂资源最新在线 | 欧美A级在线 | 深夜无码福利 | 成人国产亚洲 | 三级黄色网页 | 欧美操人 | igao视频在线| 日韩一区二区三区高清 | 国产不卡在线看 | 午夜成人影院在线观看 | 性国产在线观看 | 国产精品综合 | 国产精品无码在线 | 成人无码免费毛片A片 | 午夜小福利 | 久久色宗合| 国产原创在线 | 日韩精品福利 | 国产午夜亚洲精 | 日韩欧美体验一 | 国产精品17p| 亚洲三级黄色 | 黃色A片三級三級三級 | 国产精品熟女乱 | 日韩中文字幕精品在线 | 国产免费美女 | 日本簧片 | 国产草草| 超碰福利导航 | 日韩va天堂网 | 国产精品永久成人免费 | 乱伦一区二| 国产成人三级片网站 | 成人伦理 | 日韩国产欧美精品 | 国产精品不卡网 | 国产精品大片 | 午夜黄视频 | 免费玉足脚交视频 | 屁屁影院国产第一页 | 成人免看一级a一片 | 国产高潮在线观看 | 国产精品自在线 | 欧美乱强伦 | 又大又粗又黄又爽 | 黄色网址网站 | 国产精品色哟哟 | 日韩在线在 | 三级黄色AV | 三级片在线播放视频 | 操天天操 | 国产人妖精品 | 天天日天天干天天射 | 成人福利导航在线观看 | 日韩免费一区二区三区 | 婷婷综合五月 | 久热思思| 秋霞午夜伦理 | 日韩另类| 老熟女综合 | 国产精品一曲二曲 | 国产精品高清视 | 国产ts人妖网站 | 日韩亚洲无码操操操 | 亚洲精品国产setv | 国产成人影视在线观看 | 成人导航在线观看 | 精品三级片 | 日韩欧美亚洲每日更新 | 午夜成人免费看 | 日韩国产中文欧美 | 三级片成人在线观看 | 日韩国产精品乱码 | 午夜婷婷网 | 国产成人精品久久 | 孕妇三级片网络 | 福利一区视频在线观看 | 国产自约视频 | 色老妇女影院 | 日韩在线视频一区国产 | 狼人av伊人 | 婷婷五月综合激情 | 一区二区视频观看 | 无码专区在线观看 | 成人免费理论片 | 成人片在线观看 | 日韩欧美亚洲精品 | 日本人妻中文 | 午夜艹逼 | 国产资源精品 | 国模精品一区二区三区 | 在线播放无码不卡 | 成人高清视频 | 成人精品一区二区电影 | 五月花婷婷 | 天天日天天射天天爽 | 福利所第一导航福利 | 91视频高清 | 在线三级网址 | 五月婷婷色因 | 日韩AV二区 | 黄色av网站在线观看 | 国产精品永久成人免费 | 91插逼| 视频一二区免费 | 国产v日韩v欧美v | 日韩电影中文 | 天天日天天干天天日 | 久综合久综合 | 国产尤物在线 | 日韩无砖专区一区 | 午夜视频播放器 | 日韩一级无码 | 日韩视频三区 | 中文字幕不卡在线 | 深夜福利小视频 | 骚妇久久 | 永久免费日韩 | 玖玖爱在线看 | 日韩精品视频在线 | 日韩欧美亚洲天堂成人 | 国产在线第一页 | 成人无码A级 | 无码影视在线国产 | 91自拍视屏 | 加勒比二区 | 成人免费男女视频网 | 国产精品无码不卡 | 日韩小视频网站 | 欧美视频一区二区 | 午夜无码视频 | 成人片a免看 | 成人性生交大婬乱欧美 | 国产偷自拍 | 中文字幕久久影视 | 日韩精品影视 | 国产美女狂喷 | 国产人妖视频网站 | 都市激情亚洲 | 欧美精品综合 | 屁屁影院日韩三页 | 国产在线中文字幕 | 视频一区二区三区免费 | 成人午夜福利网 | 成人免费黄片 | 国产视频成人 | 国产成年视频 | 欧美性爱站 | 亚洲国产精品va | 日韩国产精品欧美 | 国产女主播视频 | 日韩二区在线 | 亚洲成成品网站 | 国产三级在线免费播放 | 国产91网址在线播放 | 东京99热| 成人国产高清在线 | 国产又大又黄 | 日韩午夜激情视频 | 日本激情网站 | 日韩成人在线视频网站 | 成人免费观看三级片 | 狠狠操夜夜干 | 亚洲精品爆乳无码A片 | 欧美综合性爱 | 日韩免费 | 主播二区 | 日韩高清视频 | 麻豆秘精品国产免费 | 91香蕉视 | 国产女主播一区 | 午夜成人精品视频在线 | 国产丝袜人妖在线 | 日韩视频-熊猫成人网 | 日韩中文字幕电影网站 | 91视频盛宴| 午夜福利体验区 | 日韩中文字幕区二 | 国产自在线三级片 | 东京热综合网 | 日韩网站一区二区三区 | 日韩视频免费在线观看 | 黃色A片三級三級三級 | 天天干夜夜肏 | 日韩综合欧美 | 日韩欧美中文字幕不卡 | 黄色A片网址 | 国产a∨精品一 | A级毛片大全免费 | 国产91精品 | 日韩午夜视频在线观看 | 免费黃色三級片在线 | 国产系列在线 | 国产凸凹视频一 | 黄色三级A片 | 东京热无码AV| 色窝窝在线视频 | 欧美另类玩 | 日逼网站视频 | 成人免费看视频 | 天天看夜夜操 | 日韩美女 | 超碰在线人人操 | 黑人免费视频 | 国产sm精品调 | 国产三级在线免费播放 | 国产不卡在线视频 | 自拍偷拍视频在线 | 日韩丝袜精品二区免费 | 中文字幕国产第一页 | 天天狠狠干| 国产武打片大全 | 老色网站 | 国产优物在线观看 | 成人三级网站国产 | 拍国产真实乱人偷精品 | 五月丁香婷婷综合 | 在线观看国产不卡 | 日韩福利一区 | 三级国产在线 | 日韩精品免费0 | 图片区视频区小说区 | 人妖视频网址 | 尤物在线免费视频 | 午夜影院欧美 | 丁香五月婷婷五月 | 超碰人人操人人干 | 成人亚洲国产欧美另类 | 国产玉足脚交 | 国产精品第三页 | 日韩专区不卡一区 | 性无码专区 | 爱豆传媒免费看 | 亚洲精品网站无码av | 日韩成人影院在线观看 | 成人午夜视 | 国产福利在线观 | 日韩在线网 | 成人免费片 | 午夜性网址 | 国产精品成人AV片 | 乱视频在线观看 | 日韩精品高清第一区 | 国产91精品秘入口 | 国产精品美女久 | 尤物视频在线 | 东京热无码专区 | 91视频第一页| 亚洲国产黄片 | 日本丰满少妇做爰爽爽 | 深夜福利高清无码 | 成人高清在线视频 | 国产区视频在线 | 国产精品一区久久久 | 孕妇三级片在线观看 | 麻豆国产在线 | 三级视频婷婷麻 | 国产第二区 | 二区免费视频 | 国产又大又黄又猛又爽 | 国产免费看三级片 | 日韩在线高清视频蜜桃 | 专干老熟人300部 | 三级黄色无码 | 日韩城人网站 | 天堂黄色网址 | 日韩精东 | 亚洲小格式无码 | 国产无码片 | 欧美日韩国产专区 | 日韩精品免费在线观看 | 日韩综合在线一区二区 | 日韩无码 | 日韩亚洲精品在线播放 | 久久影视综合网 | 精品盗摄 | 日韩亚洲欧洲在线观看 | 日本亚洲精品 | 日韩欧美亚洲天堂成人 | 国产自精品 | 日韩成人三级在线观看 | 日韩一区二区三在线 | 日韩国产欧美精品在线 | 日韩一二三区免费视频 | 久久不射网站 | 国产激情视频在线观看 | 国产性爱精品在线观看 | 午夜影视免费 | 天美精东在线 | 国产美女精品在线 | 国产爆乳在线播放 | 午夜福利免费在线 | 图片在线视频小说成人 | 日韩一卡2卡3卡4卡 日韩一卡2卡3 | 福利视频网址导航 | 都市激情欧美 | 都市激情亚洲 | 激情都市亚洲 | 任我操在线视频 | 国产精品码一本A片 | 日韩欧美一二三区激情 | WWW97干| 国产爆乳在线播放 | 日韩在线在线播放 | 国产孕妇一区二区三区 | 成人论坛网址 | 日韩亚洲欧美国产另类 | 黄色三级片毛片网站 | 成人福利导航大全在线 | 日韩精品第30页 | 婷婷深爱激情网 | 午夜福利导航视频 | 国产高潮白浆喷水男男 | 国产精品自拍 | 亚洲视频第一页 | 日韩欧美码| 欧美成人视屏在线 | 美女呻吟网站 | 谁有A片网址 | 拍国产真实乱人偷精品 | 福利姬免费视频 | 国产精品自拍一区 | 亚洲天天天 | 蜜桃传媒视频 | 奶大水多大乳视频 | 日韩无毒视频在线观看 | 色婷婷一区 | 日韩免费一级 | 国产午夜伦理 | 夜夜操狠狠干 | 日韩免费| 三级黄特色 | 国产浓毛大泬熟妇视频 | 加勒比在线99 | 成人不卡视频 | 性色AⅤ| 亚洲小说区图片区 | 亚洲男女视频 | 国产成年人在线观看 | 国产高清自拍一区 | 日韩高清视频 | 另类图片激情小说 | 日韩精品亚 | 免费A片网 | 日韩一区二区免费看 | 国内激情视频 | 最新A片网址 | 丁香五月婷婷网 | 国内自拍视频网 | 日韩毛片在线 | 黄色毛片免费看 | 日韩国产精品乱久 | 日韩伦理电影在线观看 | 国产大片免费线上观 | 午夜在线小视频 | 日韩伦理大片 | 日韩亚洲欧美国产另类 | 午夜日韩视频0 | 午夜男女视频0 | 麻豆传媒入口 | 日韩精品一区二区最新 | 深夜福利亚洲精品 | 日韩中文字幕综合 | 午夜福利院电影 | 亚洲卡一卡二卡三卡四 | 国产第页 | 亚洲综合日韩精品国产 | 东京热大交乱在线观看 | 午夜成人在线免费视频 | 亚洲无码午夜 | 日韩精品在线观看成人 | 欧美成人在线网站 | 日韩日本伦奷在线播放 | av在线一区二区 | 国产97swa| 激情网四房 | 福利视频网导航 | 午夜在线电影 | 国产嫩草| 国产色情av | 成人免费黄色大片 | 密桃性爱视频第一页 | 午夜成人高清无码 | 日韩专区欧美激情 | 中国一区二区精彩视频 | 日韩精品秘a在线观看 | 成人午夜A片免费看 | 国产乱人伦无码视频 | 三级网站免费观看 | 免费看A级片 | 午夜影院欧美 | 色黄国产 | 91精品秘无码网站 | 经典一区二区三区 | 91直播体育 | 日韩热映专区视频合集 | 日韩精品手机在线 | 亚洲综合激情网 | 国产精品成人自拍 | 成人免费一级A片 | 日韩一区二区三区高清 | 午夜成人免费网址 | 日韩在线欧美高清一区 | 三级片孕妇 | 97福利视频| 成人在线日韩 | 四虎传媒 | 国产精品久久久久久久 | 中文字幕丝袜 | 日韩在线19P | 日韩和的一区二区 | 国产干美女 | 乱伦日屄视频 | 成人午夜视频在线视频 | 成人毛片A片 | 日韩视频欧美视频 | 日本乱伦三级片 | 深夜成人福利网站 | 国产一区视频在线 | 三级在线观看成人 | 狼友网页 | 成人小说图片网 | 三级视品| 无码影视大全 | 熟女自拍偷拍 | 日韩在线永久免费播放 | 无码福利 | 日韩成人成色 | 国产a∨免费精品视频 | 欧美成人综合 | 免费观看三级网站 | 午夜成人AV在线播放 | 成人亚洲欧美一区 | 国产日产亚洲 | 日韩免费一区二区三区 | 超碰人人干人人摸 | 日韩无码伦理 | 韩国午夜三级 | 91丨露脸丨熟女抽搐 | 日韩亚洲欧美激情 | 国产aⅴ激情无 | 成人春色影视 | 国产图区| 欧美日韩三区 | 午夜成人精品不卡影院 | 日韩精品专区中文字幕 | 国产精品自拍网站 | 三级在线观看国产 | 国产91欧美 | 欧美多人性爱视频 | 日韩精品秘 在线观看 | 中国三级片在线观看 | 国模冰冰一区二区 | www.久久综合网 | 国产浓毛大泬熟妇视频 | 蜜桃色网 | 国产按头暴力深喉口爆 | 成人一区二区三区在线 | 成人亚洲| 韩国福利二区 | 国产精品久久在线观看 | 国产福利一区视频 | 日韩精品秘a在线观看 | 国产美女在线观看 | 日韩精品在线观看 | 三级国产| 亚洲av卡一卡二 | 午夜无码视频 | 97超碰人人干 | 日韩国产精品免费观看 | A级毛片大全免费 | 激情乱伦网站 | 日韩一区二区三区电影 | 99自拍视频在线 | 亚洲激情图片小说伦 | 91婷婷五夜天 | 91网址在线 | 性色aⅴ| 成人午夜无码福利视频 | 国产成a人 | 国产大神背着在线播放 | 国产chenre| 专干老熟人300部 | 五月婷婷丁香综合 | 91香蕉影院| 国产91精品视频网 | 91蝌蚪色 | 国产精品久久性爱视频 | 精品人妻一二三区 | 东京热入口 | 91视色| 国产乱弄免费视频观看 | 午夜成人影院在线 | 国产v亚| 精品三级片在线观看 | 国产精品成人在线 | 三级视频院 | 成人一区二区三区 | 国产精选自拍 | 日韩在线成人免费视频 | 午夜精品福利在线 | 91视频青| 国产看片在线 | 91网站地址 | 岛国大片 | 欧美精品在线一区二区 | 成人a大片在线观看 | 天堂资源最新在线 | 国产乱人妻精品秘入口 | 国产精品无码不卡 | 五月丁香六月天 | 自拍偷拍免费 | 国产高潮久久 | 成人电视一区二区 | 老湿试看| 国内乱伦网 | 国精自拍| 日韩欧美在线中文字幕 | 中国午夜精品 | 五月婷婷六月丁香 | 成人a区在线观看 | 日韩福利在线观看 | 国产成人无码av亚洲 | 欧美V∧| 日韩性爱视频在 | 欧美日韩国产一区二区 | a片在线观看网站 | 97色蜜桃网| 国产伦理精品在线 | 成人xxxxx| 三级黄色A片视频 | 欧美精品成人在线 | 国产原创视频 | 偷拍综合网| www.黄色| 国产福利一区视频 | 日韩福利在线观看 | 国产成年视频 | 91香蕉网 | 国产白浆在线观看 | 国产三级片网址 | 人人艹97 | 午夜国产无码 | 日韩制服| 午夜成人无码 | 国产拍拍 | 日韩大片高清播放器大 | 午夜肏屄 | 91一区免费高 | www、色日本 | 日韩性爱网址 | 亚洲激情综合 | 欧美另类色 | 一区不卡在线观看 | 综合视频区 | 波多野結 | 精品国产一二三 | 日韩成人国 | 自拍偷拍视频网址 | 成人午夜福利网站 | 久久主页| 精品一区二区三区人妻 | 日韩片免费 | 美女精品一区 | 私人午夜福利 | 国产乱人视频 | 日韩视频在线一区 | 日韩欧美成人影院 | 日韩欧美在线 | 日韩电影免费看 | 国产亚洲无码在线观看 | 日韩欧美一区二区三区 | 中国三级片免费看 | 精品人妖资源百度 | 福利精品国产自产在线 | 国模一区二区 | 神马AV影院 | 国产伦理电影 | 日韩国产欧美综合在线 | 亚洲视频三| 国产精品三级A | 久久国产不卡视频 | 91视频亚洲| 综合久久888| 区一区二视频 | 天天干天天弄 | 中文字幕αv | 亚洲伦理电影 | 尤物在线免费视频 | 日韩国产最新在线观看 | 精品自拍1 | 成人片免费 | 人妖操伪娘 | 亚洲无码午夜 | 午夜免费成人影院 | 国产老妇伦国 | 国产酒店偷拍 | 日韩射吧| 91自拍在线 | 日韩欧美国产高清视频 | 日韩睡熟迷奷系列精品 | 97视频| 精品国产一区二区久久 | 91丝袜在线 | 国产8区 | 国产第一页草草 | 成人福利影院在线观看 | 日韩欧美综合网 | 日韩精品小视频 | 久久影视综合2o23 | 国产999在线观看 | 日韩国产精品免费观看 | 日韩成人精品在线 | 日韩在线入口 | 国产视频福利 | 极品二区 | 欧美精品一区二区三 | 高潮喷水无码 | 97伦理电影| 国产精品成人品 | 国产AV在| 久热久草| 日韩一区二区欧美一区 | 日韩午夜伦理片 | 午夜社区在线观看 | 乱伦熟女视频 | 日韩最新国产精品网站 | 玖草视频 | 性做久久久久久久久久 | www,xxx色| 国产性色自拍网 | 日韩亚洲欧美一 | 国产69精品福利 | 日韩亚洲三级 | 不卡网久久 | 日韩网友自拍区 | 国产自户一区c | 午夜精品在线观看 | 老色网站 | 欧美性爱肏屄 | 狠狠干夜夜艹 | 爱豆传媒在线 | 日韩欧美高清 | 在线一区二区免费 | www.丁香五月天 | 日韩精品亚洲专区站 | 成人欧美一区二区三区 | 日韩电影第一页 | 福利姬液液酱喷水 | 国产清纯可爱高中害羞 | 国产无码一区二区三区 | 天堂网在线免费视频 | 午夜视频神马 | 亚洲卡一卡二在线观看 | 午夜在线电影网 | 在线观看无码不卡视频 | 日韩欧美国产亚洲中文 | 国产成人亚洲日韩 | 国产高潮在线观看 | 在线观看自拍视频 | 日韩伦理一区 | 日韩专区亚洲精品 | 国产a级片免费观看 | 97人人操| 日韩高清国产一区在线 | 91视频人人 | 密桃性爱视频第一页 | 亚洲国内自拍 | 久久综合免费 | 日韩高清一区二 | 成人三级色 | 午夜在线亚洲 | 国产日韩成| 国产高清视频在线播放 | 黄色三级免费网址 | 日韩精品黄一区二区 | 亚洲精品字幕在线观看 | 国产又粗又硬又长又爽 | 最新国产乱伦 | 国产精品xx | 日韩在线伦理片 | 国产主播资源 | 强奸乱伦小视频 | 国产亚洲AV | 18禁免费网站 | 狼友福利在线播放 | 岛国在线免费 | 午夜无码在线观看 | 国产精品美女在线观看 | 日韩精品导航 | 在线国产不卡 | 超碰97成人| 欧美孕妇一区 | 日韩欧美理论在线观 | 日韩免费AV | 欧美日韩在线观看一区 | 国产三级电影网址 | 老熟妇毛茸茸 | 国产精品自拍第一页 | 亚洲精品网站无码av | 亚洲熟妇色 | 视频一区视频二区视频 | 日韩中文高清无码 | 日韩在线视频成人 | 四虎私人影院 | 日韩人妖精品一区二区 | 护士爆乳一区二区播放 | 日韩欧美一二三区不卡 | 日韩免费观看 | 91视频下| 无码熟妇人妻又粗又硬 | 久热青草 | 国产精品一曲 | 成人欧美一 | 日韩在线二区 | 国产αv无 | 午夜在线小视频 | 国产99热99| 日韩欧美中文字幕免费 | 岛国在线观看一 | 九一九色| 岛国av网址 | 日韩欧美国产师生制服 | 午夜无码在线视频 | 日韩有码中文 | 国产嫖妓在线视频播放 | 国产白拍 | 日本黄a | 天天操天天日天天干 | 日韩一区二区三区精品 | 国产91白丝在线播放 | 国产盗摄 | 日韩第一区 | 成人午夜二级一区二区 | 国产三四区| 国产精品国三 | 成人熟女网| 成人精品国产亚洲 | 国产又粗又黄又爽视频 | 欧美a在线| 国产人妖精品视频 | 经典三级网址 | 欧美日B | 日韩欧美国产中文综合 | 国产高清视频一 | 成人午夜精 | 国产人妻精品 | 天美mv传媒 | 欧美另类变态 | 本道久久| 国产情侣亚洲 | 成人大全在线观看 | 午夜福利a | 无码在线国产 | 天天综合色 | 成人激情网| 国产第一页草草 | 久久这里只有是精品 | 亚欧美综合 | 五月亚洲 | 成人国产 | 久久精品66| 欧美性爱在线观看视频 | 超黄网站在线观看 | 日韩精品电影在线观看 | 丁香五月婷婷五月 | 日本色道xxxwww | 国产无码性| 日韩中文字幕欧美专区 | 二区在线视频 | 日韩国产亚洲91 | 精品理伦| 尤物视频免费在线观看 | 日韩女人性开 | 国产一区二 | 午夜无码在线 | 国产精品无码在线观看 | 国产二区 | 成人小说综合网 | 日韩性视频在线播 | 黄三级视频 | 日本一二三不卡 | 影音先锋777 | 免费观看三级网站 | 日韩成人免费国产电影 | 国语对白自拍 | 日韩a优精 | 亚洲无码丝袜 | 三级影视午夜影 | 成人免费视频观看 | www.尤物.com| 亚洲综合自拍 | 精品国产一区二区久久 | 亚洲国产精品电影 | 国产情侣91在 | 亚洲激情区 | 国产精久久久久久 | 国产v片在线播放 | 成人日韩电影 | 激情成人小说在线观看 | 国产第一第二区 | 美日一区| 无码不卡视频在线观看 | 三级片在线观看国产 | 成人午夜试看 | 无码电影网站 | 欧美视频一区在线观看 | 成人精品日韩一区二区 | 国产日屄 | 成人国产综 | 91网红| 国产人妖兮 | 综合视频区 | 日韩二区三区 | 日韩免费网址 | 日韩国产欧美一区二区 | 日韩无码第1页 | 久久精品骚妇内射 | 日韩欧美精品有码在线 | 国产草草视频 | 亚洲三级网址 | 性无码专区 | 亚洲国产福利 | 国产精品第一国产精品 | 国产美女裸体网站 | 上床啪啪啪在线网站 | 日韩激情在线成人 | 亚洲精品电影网 | 国产网站精品 | 日韩视频网址 | 日韩无人区码卡二卡 | 日韩中文字幕电影 | 久久性影院 | 国产三级在线免费 | 尤物视频免费在线观看 | 成人一区二区 | 国产91香蕉在线精品 | 国产哟在线观看 | 日韩中文字幕在线亚洲 | 思思久热 | 日韩欧美精品小视频 | 欧美性爱首页 | 日韩欧美国产超级视频 | 国产国产午 | 午夜日韩| 国产a∨精品一 | 午夜国产无码 | 天天操天天爽天天干 | 国产无码电影 | 啪啪啪网站在线观看 | 国产精品18| 成人一级免费激情网 | 加勒比免费视频 | 午夜免费成年人 | 91社区网址 | 国产精品一二三 | 日韩亚洲国产中文永久 | 久久私人影院 | 成人午夜福利在线观看 | 老司机专属福利院 | 日韩精品视频免费 | 日韩电影免费在线 | 成人激情av网 | 深夜免费福利视频 | 另类老熟女 | 国产做A∨在线 | 91巨炮在线 | 日韩在线永久免费播 | 最新国产三级在线观看 |