<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    走在架構(gòu)師的大道上 Jack.Wang's home

    Java, C++, linux c, C#.net 技術(shù),軟件架構(gòu),領(lǐng)域建模,IT 項目管理 Dict.CN 在線詞典, 英語學(xué)習(xí), 在線翻譯

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
      本文來源不詳!

    何時使用分層技術(shù)?

    分層技術(shù)實際上是把技術(shù)復(fù)雜化了。和以往簡單的CS結(jié)構(gòu)的系統(tǒng)不同,分層往往需要使用特定的技術(shù)平臺來實現(xiàn)。當(dāng)然,不使用這些技術(shù)平臺也是可能的,但是效果可能就沒有那么好了。支持分層技術(shù)的平臺有很多,包括目前主流的J2EE和.NET。甚至在不同廠商的開發(fā)平臺上,要求也不一樣。使用分層技術(shù)實現(xiàn)的多層架構(gòu),成本要比普通的CS架構(gòu)高得多。

    這就產(chǎn)生了一個非常現(xiàn)實的問題-并不是所有的軟件都適合采用分層技術(shù)的。一般來說,小型的軟件使用分層并沒有太大的意義,因為分層導(dǎo)致的成本超過它所能帶來的好處。在一般的CS結(jié)構(gòu)中,可以把界面控制、邏輯處理和數(shù)據(jù)庫訪問都放在一塊兒。這種設(shè)計方式在純粹的多層主義者看來簡直就是十惡不赦。但是對于小型的軟件而言,這并不是什么大不了的事情。因為從表示層到數(shù)據(jù)層的整套功能都被囊括在一個功能塊中,同樣能夠?qū)崿F(xiàn)較好的封裝。而且,如果結(jié)構(gòu)設(shè)計的足夠好,也能夠避免表示層、業(yè)務(wù)層和數(shù)據(jù)層之間出現(xiàn)過高的耦合度。因此,除非確實需要,不然沒有必要使用分層技術(shù)。

    尤其在處理一些特殊的項目時,嚴(yán)格的區(qū)分三層結(jié)構(gòu)并不理想。比如在快速開發(fā)windows界面的應(yīng)用時,往往會用到一些對數(shù)據(jù)庫敏感的控件,這種處理方法跨越了三個層次,但是卻很實用,成本也比較低。又比如一些框架,給出了從界面層到數(shù)據(jù)庫的綜合的解決方案,和windows的應(yīng)用類似,嚴(yán)格的三層技術(shù)也不適用于這種情況。

    如何使用分層技術(shù)?

    從某種意義上來看,層其實是一個粗粒度的組件。就像我們使用組件技術(shù)是為了對系統(tǒng)進(jìn)行一種劃分一樣,層的一個很大的作用也是如此。其目的是為了系統(tǒng)更容易被理解,不同的部分能夠被較容易的替換。

    使用分層技術(shù)的依據(jù)是軟件開發(fā)人員的實際需要。如果你是在使用某些優(yōu)秀的面向?qū)ο蟮能浖_發(fā)平臺的話,那它們一般都會建議(或是強(qiáng)制)你使用某一種分層機(jī)制。這是你采用分層技術(shù)的一大參考。

    對于大多數(shù)有一定經(jīng)驗的軟件團(tuán)隊而言,一般都會積累一些軟件開發(fā)經(jīng)驗。其中包含了很多在某些特定的領(lǐng)域中使用的基礎(chǔ)的類或組件。這些元素構(gòu)成了一個系統(tǒng)的通用層次。這個層次也是分層時需要考慮的。例如一些應(yīng)用軟件中使用的一些通用的Currency對象或是Organization對象。分析模式一書對此類的對象進(jìn)行了充分細(xì)致的闡述。這個層次一般被稱為跨領(lǐng)域?qū)樱╟ross-domain layer),或稱為工具層(utility layer)。

    目前的很多軟件都采用了數(shù)據(jù)庫映射技術(shù)。數(shù)據(jù)庫映射層對于企業(yè)應(yīng)用系統(tǒng)非常的重要,因此也需要納入考慮之列。數(shù)據(jù)庫映射技術(shù)用起來簡單,但是要實現(xiàn)可不容易。如果不是非常有必要,盡可能使用現(xiàn)成的框架,或是采用其中部分的設(shè)計思路。試圖構(gòu)建一個大而全的映射層次的代價是非常高昂的,認(rèn)識不到這一點會帶來很大的麻煩。數(shù)據(jù)庫映射技術(shù)的知識,我們在下文中還有專門的篇幅來討論。

    如何存放數(shù)據(jù)(狀態(tài))?

    在學(xué)習(xí)EJB的過程中,最先要理解的一定是有狀態(tài)和無狀態(tài)的概念。可以說,整個概念是多層體系的核心。為什么這么說呢?這里的狀態(tài)指的是類的狀態(tài),例如類的屬性、變量等。由于狀態(tài)的不同,類也表現(xiàn)出差異來。而對于多層結(jié)構(gòu)的軟件,創(chuàng)建和銷毀一個類的開銷是很大的,如果該軟件支持分布式的話尤為如此。所以如果系統(tǒng)的不同層次間進(jìn)行頻繁的調(diào)用-創(chuàng)建一個類,再銷毀一個類。這種做法是非常消耗資源的。在應(yīng)用系統(tǒng)的設(shè)計中,一般不單獨使用COM,就是這個原因。所以我們很自然的想到了一種經(jīng)典的設(shè)計-緩沖池。把對象存放在緩沖池中,當(dāng)需要的時候從池中取出一個,當(dāng)不需要的時候再把對象放入池中。這種設(shè)計思路能夠大幅度的提高效率。但是這對能夠放在池中的對象也提出了苛刻的要求-所有的對象必須是無差異的,也就是無狀態(tài)的。只有這樣才能夠?qū)崿F(xiàn)緩沖池。

    一般來說,對象緩沖池的技術(shù)是用在中間的業(yè)務(wù)層上的。既然中間業(yè)務(wù)層上不能夠保留有狀態(tài),那就出現(xiàn)了一個狀態(tài)轉(zhuǎn)移的問題。這里有兩種的選擇,一種是前移,把狀態(tài)移到用戶端,最典型的是使用cookie。這種選擇一般是由于狀態(tài)和用戶端有關(guān),不需要長時間保存。另一種選擇是后移,把狀態(tài)移到數(shù)據(jù)層,由數(shù)據(jù)庫來實現(xiàn)持久性狀態(tài),當(dāng)需要時才把狀態(tài)提交給業(yè)務(wù)層。這種方式是企業(yè)應(yīng)用軟件中采用最多的,但是也增大了數(shù)據(jù)庫的負(fù)擔(dān)。

    處理好接口

    由于使用了分層技術(shù),因此原先那種在CS結(jié)構(gòu)中類之間存在復(fù)雜關(guān)系就有必要重新評估了。一般層間的耦合度不宜過大。因此需要慎重的設(shè)計層之間的類調(diào)用方式。一些分布式軟件體系(例如J2EE)對層之間的調(diào)用方式以接口的形式給出了要求。同時,不同層之間僅僅知道目標(biāo)層的接口,而不知道目標(biāo)層的具體實現(xiàn)。EJB的home接口和remote接口就是這樣。在COM+體系中,也需要在設(shè)計類的同時,把接口公布出來,以供客戶方使用。

    在設(shè)計層間的接口時,除了考慮開發(fā)平臺的約束之外,還有一點是開發(fā)人員必須考慮的。那就是業(yè)務(wù)需要。業(yè)務(wù)層中往往有非常多的對象和方法,它們之間的關(guān)系也非常的負(fù)責(zé),但對于其它的層次來說,它并不關(guān)心這些細(xì)節(jié)。因此業(yè)務(wù)層公布的接口必須要簡單,而且和實現(xiàn)無關(guān)。因此,可以使用設(shè)計模式的Facade模式來簡化層間的接口。這種做法非常有效,EJB中的SessionBean和EntityBean區(qū)分就含有這種設(shè)計思路。

    同樣的,不同層之間的數(shù)據(jù)傳遞也存在問題。如果不同層的物理節(jié)點在一起還好辦,如果不在一起,那就需要使用到分布式技術(shù)了。因為不同機(jī)器的內(nèi)存地址編碼是不同的,如果接口之間采用對象引用的方式,那一定會出現(xiàn)問題。因此會將對象打包成字符串,發(fā)送到目標(biāo)機(jī)器后再還原為對象。所有的分布式平臺都提供了對這種技術(shù)的支持,這里就不多說了。但是這種實現(xiàn)技術(shù)會對我們的設(shè)計思路產(chǎn)生影響,少量的數(shù)據(jù)直接使用字符串來傳遞,數(shù)據(jù)量大的話,就需要使用封裝了數(shù)據(jù)的對象。這類對象的設(shè)計需要非常的小心。在設(shè)計過程中可以參照開發(fā)平臺提供的一些標(biāo)準(zhǔn)做法。同樣的,數(shù)據(jù)的請求的頻率也是難點之一。過于頻繁的操作來自后端的數(shù)據(jù)會加大系統(tǒng)的開銷。因此,在設(shè)計調(diào)用方法時同樣需要結(jié)合實際應(yīng)用來考慮。

    兼顧效率

    一般來說,純粹的面向?qū)ο笤O(shè)計者設(shè)計出的軟件都會比較完美。但是需要付出一定的代價。在一些大的軟件平臺上編程的時候,往往需要利用到平臺的一些機(jī)制。最典型的就是平臺的事務(wù)機(jī)制(最典型的包括J2EE平臺的JTS,以及COM+平臺的MTS),但是事務(wù)機(jī)制的實現(xiàn)往往需要平臺大量對象的支撐。這種情況下,創(chuàng)建一個支持事務(wù)的對象的開銷是很大的。處理這種問題有一種變通的辦法,就是僅僅對需要事務(wù)支撐的對象提供事務(wù)支持。這就意味著,一個單獨的業(yè)務(wù)實體類,可能需要根據(jù)是否支持事務(wù)分為兩種類:對該業(yè)務(wù)實體的select方法不需要事務(wù)的支持,只有update和delete方法才需要有事務(wù)的支持。這是不符合純面向?qū)ο笤O(shè)計者的觀點的。但是這種做法卻可以獲得比較優(yōu)秀的效率。 

    應(yīng)該承認(rèn),這種提高效率的做法加大了復(fù)雜度。因為對于客戶端來說,它們并不關(guān)心具體的實現(xiàn)技術(shù)。要求客戶端在某一種情況下調(diào)用這個類,在其它情況下又調(diào)用另一個類,這種做法既不符合面向?qū)ο蟮脑O(shè)計思路,也增大了層間耦合度及復(fù)雜性。因此,我們可以考慮使用接口或是外觀類(參見設(shè)計模式一書中的facade模式),把具體的實現(xiàn)封裝起來,而只把用戶關(guān)心的部分提供給用戶。這方面的技巧我們在下面的章節(jié)中還會提到。

    以迭代的方式進(jìn)行分層

    軟件設(shè)計中的迭代做法同樣可以適用于分層。根據(jù)自己的經(jīng)驗,在一開始就定義好所有的層次是很難的。除非有著非常豐富的經(jīng)驗,都則實現(xiàn)和原先的設(shè)計總有或大或小的差距。因此調(diào)整勢在必行。每一次的迭代都能夠?qū)Ψ謱蛹夹g(shù)進(jìn)行改進(jìn),并為后一個項目積累了經(jīng)驗。

    這里的分層迭代不可以過于頻繁,每一次的迭代都是對架構(gòu)的重大修改,都是需要投入人力的,而且會影響到軟件開發(fā)的進(jìn)度。但是成功的迭代的效果是非常明顯的,能夠在接下來的開發(fā)周期中起到穩(wěn)定架構(gòu),減少代碼量,提升軟件質(zhì)量的功效。注意,不要讓新潮技術(shù)成為分層迭代的推動力。這是開發(fā)人員都常犯的毛病,這并不是什么缺點,只能稱為一種職業(yè)病吧。分層迭代的推動力應(yīng)該源自于需求的演進(jìn)以及現(xiàn)有架構(gòu)的不穩(wěn)定已經(jīng)妨礙了軟件進(jìn)一步的開發(fā)。因此這需要團(tuán)隊中的技術(shù)主管對技術(shù)有著非常好的把握。

    重構(gòu)能夠?qū)Φ兴鶐椭P岢龃a中隱藏的壞味道并加以改進(jìn)。應(yīng)該說,迭代是一種比較激烈的做法,更好的做法是在開發(fā)中不斷的對架構(gòu)、層次進(jìn)行調(diào)整。但這對團(tuán)隊、技術(shù)、方法、過程都有著很高的要求。因此迭代仍然是一種主要的改進(jìn)手段。

    層內(nèi)的細(xì)分

    分層的思路還可以適用于層的內(nèi)部。層內(nèi)的細(xì)分并沒有固定的方式,其驅(qū)動因素往往是出于封裝性和重用的考慮。例如,在EJB體系中的業(yè)務(wù)層中,實體Bean負(fù)責(zé)實現(xiàn)業(yè)務(wù)對象,因此一個應(yīng)用往往擁有大量的實體Bean。而用戶端并不需要了解每一個的實體Bean,對它們來說,只要能夠完全一些業(yè)務(wù)邏輯就可以了,但完成這些業(yè)務(wù)邏輯則需要和多個實體Bean打交道。因此EJB提供了會話Bean,來負(fù)責(zé)把實體Bean封裝起來,用戶只知道會話Bean,不知道實體Bean的存在。這樣既保證了實體Bean的重用性,又很好的實現(xiàn)了封裝。

    面向接口編程

    在前面的章節(jié)中,我們提到一個接口設(shè)計的例子。為什么我們提倡接口的設(shè)計呢?Martin Fowler在他的分析模式一書中指出,分析問題應(yīng)該站在概念的層次上,而不是站在實現(xiàn)的層次上。什么叫做概念的層次呢?簡單的說就是分析對象該做什么,而不是分析對象怎么做。前者屬于分析的階段,后者屬于設(shè)計甚至是實現(xiàn)的階段。在需求工程中有一種稱為CRC卡片的玩藝兒,是用來分析類的職責(zé)和關(guān)系的,其實那種方法就是從概念層次上進(jìn)行面向?qū)ο笤O(shè)計。因此,如果要從概念層次上進(jìn)行分析,這就要求你從領(lǐng)域?qū)<业慕嵌葋砜创绦蚴侨绾伪硎粳F(xiàn)實世界中的概念的。下面的這句話有些拗口,從實現(xiàn)的角度上來說,概念層次對應(yīng)于合同,合同的實現(xiàn)形式包括接口和基類。簡單的說吧,在概念層次上進(jìn)行分析就是設(shè)計出接口(或是基類),而不用關(guān)心具體的接口實現(xiàn)(實現(xiàn)推遲到子類再實現(xiàn))。結(jié)合上面的論述,我們也可以這樣推斷,接口應(yīng)該是要符合現(xiàn)實世界的觀念的。

    在Martin Fowler的另一篇著作中提到了這樣一個例子,非常好的解釋了接口編程的思路:

    interface Person {

     public String name();

     public void name(String newName);

     public Money salary ();

     public void salary (Money newSalary);

     public Money payAmount ();

     public void makeManager ();

    }

    interface Engineer extends Person{

     public void numberOfPatents (int value);

     public int numberOfPatents ();

    }

    interface Salesman extends Person{

     public void numberOfSales (int numberOfSales);

     public int numberOfSales ();

    }

    interface Manager extends Person{

     public void budget (Money value);

     public Money budget ();

    }

    可以看到,為了表示現(xiàn)實世界中人(這里其實指的是員工的概念)、工程師、銷售員、經(jīng)理的概念,代碼根據(jù)人的自然觀點設(shè)計了繼承層次結(jié)構(gòu),并很好的實現(xiàn)了重用。而且,我們可以認(rèn)定該接口是相對穩(wěn)定的。我們再來看看實現(xiàn)部分:

    public class PersonImpFlag implements Person, Salesman, Engineer,Manager{

    // Implementing Salesman

    public static Salesman newSalesman (String name){

     PersonImpFlag result;

     result = new PersonImpFlag (name);

     result.makeSalesman();

     return result;

    };

    public void makeSalesman () {

     _jobTitle = 1;

    };

    public boolean isSalesman () {

     return _jobTitle == 1;

    };

    public void numberOfSales (int value){

     requireIsSalesman () ;

     _numberOfSales = value;

    };

    public int numberOfSales () {

     requireIsSalesman ();

     return _numberOfSales;

    };

    private void requireIsSalesman () {

     if (! isSalesman()) throw new PreconditionViolation ("Not a Salesman") ;

    };

     private int _numberOfSales;

     private int _jobTitle;

    }

    這是其中一種被稱為內(nèi)部標(biāo)示(Internal Flag)的實現(xiàn)方法。這里我們只是舉出一個例子,實際上我們還有非常多的解決方法,但我們并不關(guān)心。因為只要接口足夠穩(wěn)定,內(nèi)部實現(xiàn)發(fā)生再大的變化都是允許的。如果對實現(xiàn)的方式感興趣,可以參考Matrin Fowler的角色建模的文章或是我在閱讀這篇文章的一篇筆記。

    通過上面的例子,我們可以了解到,接口和實現(xiàn)分離的最大好處就是能夠在客戶端未知的情況下修改實現(xiàn)代碼。這個特性對于分層技術(shù)是非常適用的。一種是用在層和層之間的調(diào)用。層和層之間是最忌諱耦合度過高或是改變過于頻繁的。設(shè)計優(yōu)秀的接口能夠解決這個問題。另一種是用在那些不穩(wěn)定的部分上。如果某些需求的變化性很大,那么定義接口也是一種解決之道。舉個不恰當(dāng)?shù)睦樱O(shè)計良好的接口就像是我們?nèi)粘J褂玫娜f用插座一樣,不論插頭如何變化,都可以使用。

    最后強(qiáng)調(diào)一點,良好的接口定義一定是來自于需求的,它絕對不是程序員絞盡腦汁想出來的。

    數(shù)據(jù)映射層

    在各個層的設(shè)計中,可能比較令人困惑的就是數(shù)據(jù)映射層了。由于篇幅的關(guān)系,我們不可能在這個問題上討論太多,只能是拋磚引玉。如果有機(jī)會,我們還可以來談?wù)勥@方面的話題。

    面向?qū)ο蠹夹g(shù)已經(jīng)成為軟件開發(fā)的一種趨勢,越來越多的人開始了解、學(xué)習(xí)和使用面向?qū)ο蠹夹g(shù)。而大多數(shù)的面向?qū)ο蠹夹g(shù)都只是解決了內(nèi)存中的面向?qū)ο蟮膯栴}。但是鮮有提到持久性的面向?qū)ο髥栴}。

    面向?qū)ο笤O(shè)計的機(jī)制與關(guān)系模型有很大的不同,這造成了面向?qū)ο笤O(shè)計與關(guān)系數(shù)據(jù)庫設(shè)計之間的不匹配。面向?qū)ο笤O(shè)計的基本理論包括耦合、聚合、封裝、繼承、多態(tài),而關(guān)系數(shù)據(jù)模型的理論則完全不同,它的基本原理是數(shù)據(jù)庫的三大范式。最明顯的一個例子是,Order對象包括一組的OrderItem對象,因此我們需要在Order類中設(shè)計一個容器(各個編程語言都提供了一組的容器對象及相關(guān)操作以供使用)來存儲OrderItem,也就是說Order類中的指針指向OrderItem。假設(shè)Order類和OrderItem分別對應(yīng)于數(shù)據(jù)庫的兩張表(最簡單的映射情況),那么,我們要實現(xiàn)二者之間的關(guān)系,是通過在OrderItem表(假設(shè)名稱一樣)增加指向Order表的外鍵。這是兩種完全不同的設(shè)置。數(shù)據(jù)映射層的作用就是向用戶端隱藏關(guān)系數(shù)據(jù)庫的存在。

    自己開發(fā)一個對象/關(guān)系映射工具是非常誘人的。但是應(yīng)該考慮到,開發(fā)這樣一個工具并不是一件容易的事,需要付出很大的成本。尤其是手工處理數(shù)據(jù)一致性和事務(wù)處理的問題上。它比你想象的要難的多。因此,獲取一個對象/關(guān)系映射工具的最好途徑是購買,而不是開發(fā)。

    總結(jié)

    分層對現(xiàn)代的軟件開發(fā)而言是非常重要的概念。也是我們必須學(xué)習(xí)的知識。分層的總體思路并沒有什么特別的地方,但是要和自己的開發(fā)環(huán)境、應(yīng)用環(huán)境結(jié)合起來,你還需要付出很多的努力才行。

    在完成了分層之后,軟件架構(gòu)其實已經(jīng)清晰化了。





    本博客為學(xué)習(xí)交流用,凡未注明引用的均為本人作品,轉(zhuǎn)載請注明出處,如有版權(quán)問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學(xué)習(xí)進(jìn)步。
    posted on 2008-11-14 21:14 Jack.Wang 閱讀(4892) 評論(6)  編輯  收藏 所屬分類: 架構(gòu)師篇

    Feedback

    # re: 架構(gòu)中的分層技術(shù) 2008-11-15 09:20 fyunli
    開篇就有問題,所謂某些平臺支持分層,某些則不支持是不對的。
    無論你什么環(huán)境,使用什么語言,都可以做到良好的分層。  回復(fù)  更多評論
      

    # re: 架構(gòu)中的分層技術(shù) 2008-11-15 11:16 支持下個人主頁 life126.com
    好文章,應(yīng)用起來大家都顧不上這個了
      回復(fù)  更多評論
      

    # re: 架構(gòu)中的分層技術(shù) 2008-11-16 13:51 Jack.Wang
    分層是軟件架構(gòu)的基本理論。任何軟件在邏輯上都可以分層,也可以適當(dāng)?shù)挠成涞轿锢韺哟紊希劣谠趺捶郑侄嗌賹樱灰值纫茨愕能浖I(lǐng)域(每個領(lǐng)域都有一些現(xiàn)成的架構(gòu)模式可以參考,所謂領(lǐng)域架構(gòu)),在拿到需求的時候我們習(xí)慣上進(jìn)行水平和垂直的分割,其實分層技術(shù)也是一種基本的架構(gòu)模式。  回復(fù)  更多評論
      

    # re: 架構(gòu)中的分層技術(shù) 2008-11-17 10:50 程序人生-天津
    理論說的很不錯,但是有一個問題,軟件在設(shè)計的時候,我們遵循的其實就是需求,如何分層,使用什么技術(shù),都是要看具體的項目來說的,所以,理論并不一定適合實際的應(yīng)用,期待For應(yīng)用方面的好文章  回復(fù)  更多評論
      

    # re: 架構(gòu)中的分層技術(shù) 2008-11-19 20:18 網(wǎng)站優(yōu)化
    無論你什么環(huán)境,使用什么語言,都可以做到良好的分層。  回復(fù)  更多評論
      

    # re: 架構(gòu)中的分層技術(shù) 2009-04-03 15:09 支持下個人主頁 life126.com
    看系統(tǒng)的繁雜程度,分層技術(shù)的使用由系統(tǒng)的復(fù)雜性和后續(xù)可能的維護(hù)性才需要  回復(fù)  更多評論
      

    主站蜘蛛池模板: 花蝴蝶免费视频在线观看高清版| 亚洲一区二区三区在线播放| 国产情侣久久久久aⅴ免费 | 久久免费99精品国产自在现线| 亚洲AV无码专区在线亚| 亚洲VA成无码人在线观看天堂| 国产成人青青热久免费精品| 免费在线视频你懂的| 久久国产精品成人免费| 中文在线观看免费网站| 欧洲美女大片免费播放器视频| 亚洲欧美日韩中文高清www777 | 最近最新高清免费中文字幕| 国产A∨免费精品视频| 色妞www精品视频免费看| 国产精品亚洲精品观看不卡| 亚洲天天做日日做天天看| 久久久久亚洲Av片无码v | 久久国产乱子伦精品免费看| 久久国产精品免费一区二区三区| 黄色片网站在线免费观看| 日本亚洲欧美色视频在线播放| 国产精品高清视亚洲一区二区| 亚洲成av人片不卡无码| 亚洲一区二区成人| 亚洲午夜精品一区二区| 亚洲国产精品久久久久久| 久久亚洲国产精品五月天| 亚洲福利在线视频| 亚洲第一精品福利| 91亚洲va在线天线va天堂va国产| 亚洲网址在线观看你懂的| 亚洲视频一区二区在线观看| 亚洲综合自拍成人| 亚洲欧洲日产专区| 亚洲91精品麻豆国产系列在线| 亚洲乱码无限2021芒果| 亚洲精品久久无码| 深夜福利在线免费观看| 一级做a爰片久久毛片免费陪| 国产精品成人免费观看|