向依賴關(guān)系宣戰(zhàn) 依賴倒置、控制反轉(zhuǎn)和依賴注入辨析_第1頁(yè)
向依賴關(guān)系宣戰(zhàn) 依賴倒置、控制反轉(zhuǎn)和依賴注入辨析_第2頁(yè)
向依賴關(guān)系宣戰(zhàn) 依賴倒置、控制反轉(zhuǎn)和依賴注入辨析_第3頁(yè)
向依賴關(guān)系宣戰(zhàn) 依賴倒置、控制反轉(zhuǎn)和依賴注入辨析_第4頁(yè)
向依賴關(guān)系宣戰(zhàn) 依賴倒置、控制反轉(zhuǎn)和依賴注入辨析_第5頁(yè)
已閱讀5頁(yè),還剩10頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、向依賴關(guān)系宣戰(zhàn)依賴倒置、控制反轉(zhuǎn)和依賴注 入辨析2011年04月04日13:18來(lái)源:普索網(wǎng)|關(guān)鍵詞:依賴 關(guān)系宣戰(zhàn)倒置控制反轉(zhuǎn)轉(zhuǎn)載自: HYPERLINK /archive/2005/06/27/181878.html /archive/2005/06/27/181878.html在道法自然一一面向?qū)ο髮?shí)踐指南一書中,我們采用了一個(gè)對(duì)立統(tǒng)一的辯證關(guān)系來(lái) 說(shuō)明“模板方法”模式一一 “正向依賴vs.依賴倒置”(參見(jiàn):道法自然第15章王 詠武,王詠剛2004)。這種把“好萊塢”原則和“依賴倒置”原則等量齊觀的看法其實(shí) 來(lái)自于輕量級(jí)容器PicoContainer主頁(yè)上的一段話:“控制反轉(zhuǎn)(Inver

2、sion of Control)的一個(gè)著名的同義原則是由Robert C. Martin 提出的依賴倒置原則(Dependency Inversion Principle),它的另一個(gè)昵稱是好萊塢原則 (Hollywood Principle:不要調(diào)用我,讓我來(lái)調(diào)用你)”PicoContainer 2004。和網(wǎng)友們?cè)贑SDNBlog上進(jìn)行了深入的討論后,我又把這些概念重新梳理了一下。我發(fā) 現(xiàn),這幾個(gè)概念雖然在思路和動(dòng)機(jī)等宏觀層面上是統(tǒng)一的,但在具體的應(yīng)用層面還是存在著 許多很微妙的差別。本文通過(guò)幾個(gè)簡(jiǎn)單的例子對(duì)依賴倒置(Dependency Inversion Principle)、控制反轉(zhuǎn)

3、(Inversion of Control)、依賴注入(Dependency Injection) 等概念進(jìn)行了更為深入的辨析,也算是對(duì)于道法自然正文內(nèi)容的一個(gè)補(bǔ)充吧。依賴和耦合(Dependency and Coupling )在道法自然一一面向?qū)ο髮?shí)踐指南一書中,我們采用了一個(gè)對(duì)立統(tǒng)一的辯證關(guān)系來(lái) 說(shuō)明“模板方法”模式一一 “正向依賴vs.依賴倒置”(參見(jiàn):道法自然第15章王 詠武,王詠剛2004)。這種把“好萊塢”原則和“依賴倒置”原則等量齊觀的看法其實(shí) 來(lái)自于輕量級(jí)容器PicoContainer主頁(yè)上的一段話:首先來(lái)看一下依賴和耦合的概念。Rational Rose的幫助文檔上是這樣定

4、義“依賴”關(guān)系的:“依賴描述了兩個(gè)模型元素 之間的關(guān)系,如果被依賴的模型元素發(fā)生變化就會(huì)影響到另一個(gè)模型元素。典型的,在類圖 上,依賴關(guān)系表明客戶類的操作會(huì)調(diào)用服務(wù)器類的操作。”Martin Fowler在Reducing Coupling一文中這樣描述耦合:“如果改變程序的一 個(gè)模塊要求另一個(gè)模塊同時(shí)發(fā)生變化,就認(rèn)為這兩個(gè)模塊發(fā)生了耦合?!?Fowler 2001從上面的定義可以看出:如果模塊A調(diào)用模塊B提供的方法,或訪問(wèn)模塊B中的某些數(shù) 據(jù)成員(當(dāng)然,在面向?qū)ο箝_發(fā)中一般不提倡這樣做),我們就認(rèn)為模塊A依賴于模塊B, 模塊A和模塊B之間發(fā)生了耦合。那么,依賴對(duì)于我們來(lái)說(shuō)究竟是好事還是壞事呢

5、?由于人類的理解力有限,大多數(shù)人難以理解和把握過(guò)于復(fù)雜的系統(tǒng)。把軟件系統(tǒng)劃分成 多個(gè)模塊,可以有效控制模塊的復(fù)雜度,使每個(gè)模塊都易于理解和維護(hù)。但在這種情況下, 模塊之間就必須以某種方式交換信息,也就是必然要發(fā)生某種耦合關(guān)系。如果某個(gè)模塊和其 它模塊沒(méi)有任何關(guān)聯(lián)(哪怕只是潛在的或隱含的依賴關(guān)系),我們就幾乎可以斷定,該模塊 不屬于此軟件系統(tǒng),應(yīng)該從系統(tǒng)中剔除。如果所有模塊之間都沒(méi)有任何耦合關(guān)系,其結(jié)果必 然是:整個(gè)軟件不過(guò)是多個(gè)互不相干的系統(tǒng)的簡(jiǎn)單堆積,對(duì)每個(gè)系統(tǒng)而言,所有功能還是要 在一個(gè)模塊中實(shí)現(xiàn),這等于沒(méi)有做任何模塊的分解。因此,模塊之間必定會(huì)有這樣或那樣的依賴關(guān)系,永遠(yuǎn)不要幻想消除所有

6、依賴。但是, 過(guò)強(qiáng)的耦合關(guān)系(如一個(gè)模塊的變化會(huì)造成一個(gè)或多個(gè)其他模塊也同時(shí)發(fā)生變化的依賴關(guān) 系)會(huì)對(duì)軟件系統(tǒng)的質(zhì)量造成很大的危害。特別是當(dāng)需求發(fā)生變化時(shí),代碼的維護(hù)成本將非 常高。所以,我們必須想盡辦法來(lái)控制和消解不必要的耦合,特別是那種會(huì)導(dǎo)致其它模塊發(fā) 生不可控變化的依賴關(guān)系。依賴倒置、控制反轉(zhuǎn)、依賴注入等原則就是人們?cè)诤鸵蕾囮P(guān)系進(jìn) 行艱苦卓絕的斗爭(zhēng)過(guò)程中不斷產(chǎn)生和發(fā)展起來(lái)的。接口和實(shí)現(xiàn)分離把接口和實(shí)現(xiàn)分開是人們?cè)噲D控制依賴關(guān)系的第一個(gè)嘗試,圖1是Robert C. Martin在依賴倒置Martin 1996 一文中所舉的第一個(gè)例子。其中,ReadKeyboard()和WritePrin

7、ter()為函數(shù)庫(kù)中的兩個(gè)函數(shù),應(yīng)用程序循環(huán)調(diào)用這兩個(gè)函數(shù),以便把用戶鍵入的 字符拷貝到打印機(jī)輸出。為了使應(yīng)用程序不依賴于函數(shù)庫(kù)的具體實(shí)現(xiàn),C語(yǔ)言把函數(shù)的定義寫在了一個(gè)分離的頭 文件(函數(shù)庫(kù).h)中。這種做法的好處是:雖然應(yīng)用程序要調(diào)用函數(shù)庫(kù)、依賴于函數(shù)庫(kù),但 是,當(dāng)我們要改變函數(shù)庫(kù)的實(shí)現(xiàn)時(shí),只要重寫函數(shù)的實(shí)現(xiàn)代碼,應(yīng)用程序無(wú)需發(fā)生變化。例 如,改變函數(shù)庫(kù).c文件,把WritePrinter ()函數(shù)重新實(shí)現(xiàn)成向磁盤中輸出,這時(shí)只要將應(yīng) 用程序和函數(shù)庫(kù)重新鏈接,程序的功能就會(huì)發(fā)生相應(yīng)的變化。上面的函數(shù)庫(kù)也可以采用C+語(yǔ)言來(lái)實(shí)現(xiàn)。我們通常把這種用面向?qū)ο蠹夹g(shù)實(shí)現(xiàn)的,為 應(yīng)用程序提供多個(gè)支持類的模

8、塊稱為“類庫(kù)”,如圖2所示。這種通過(guò)分離接口和實(shí)現(xiàn)來(lái) 消解應(yīng)用程序和類庫(kù)之間依賴關(guān)系的做法具有以下特點(diǎn):應(yīng)用程序調(diào)用類庫(kù),依賴于類庫(kù)。接口和實(shí)現(xiàn)的分離從一定的程度上消解了這個(gè)依賴關(guān)系,具體實(shí)現(xiàn)可以在編譯期間 發(fā)生變化。但是,這種消解方法的作用非常有限。比如說(shuō),一個(gè)系統(tǒng)中無(wú)法容納多個(gè)實(shí)現(xiàn), 不同的實(shí)現(xiàn)不能動(dòng)態(tài)發(fā)生變化,用WritePrinter函數(shù)名來(lái)實(shí)現(xiàn)向磁盤中輸出的功能也顯得 非常古怪,等等。類庫(kù)可以單獨(dú)重用。但是應(yīng)用程序不能脫離類庫(kù)而重用,除非提供一個(gè)實(shí)現(xiàn)了相同 接口的類庫(kù)。依賴倒置(Dependency Inversion Principle)可以看出,上面討論的簡(jiǎn)單分離接口的方法對(duì)于依

9、賴關(guān)系的消解作用非常有限。Java 語(yǔ)言提供了純粹的接口類,這種接口類不包括任何實(shí)現(xiàn)代碼,可以更好地隔離兩個(gè)模塊C+ 語(yǔ)言中雖然沒(méi)有定義這種純粹的接口類,但所有成員函數(shù)都是純虛函數(shù)的抽象類也不包含任 何實(shí)現(xiàn)代碼,可以起到類似于Java接口類的作用。為了和上一節(jié)中提到的簡(jiǎn)單接口相區(qū)別, 本文后面將把基于Java接口類或C+抽象類定義的接口稱為抽象接口。依賴倒置原則就是 建立在抽象接口的基礎(chǔ)上的。Robert Martin這樣描述依賴倒置原則Martin 1996:上層模塊不應(yīng)該依賴于下層模塊,它們共同依賴于一個(gè)抽象。抽象不能依賴于具象,具象依賴于抽象。其含義是:為了消解兩個(gè)模塊間的依賴關(guān)系,應(yīng)該

10、在兩個(gè)模塊之間定義一個(gè)抽象接口, 上層模塊調(diào)用抽象接口定義的函數(shù),下層模塊實(shí)現(xiàn)該接口。如圖3所示,對(duì)于上一節(jié)的例 子,我們可以定義兩個(gè)抽象類Reader和Writer作為抽象接口,其中的Read()和Write() 函數(shù)都是純虛函數(shù),而具體的KeyboardReader和PrinterWriter類實(shí)現(xiàn)了這些接口。當(dāng)應(yīng) 用程序調(diào)用Read()和Write()函數(shù)時(shí),由于多態(tài)性機(jī)制的作用,實(shí)際調(diào)用的是具體的 KeyboardReader和PrinterWriter類中的實(shí)現(xiàn)。因此,抽象接口隔離了應(yīng)用程序和類庫(kù)中 的具體類,使它們之間沒(méi)有直接的耦合關(guān)系,可以獨(dú)立地?cái)U(kuò)展或重用。例如,我們可以用類 似

11、的方法實(shí)現(xiàn)FileReader或DiskWriter類,應(yīng)用程序既可以根據(jù)需要選擇從鍵盤或文件輸 入,也可以選擇向打印機(jī)或磁盤輸出,甚至同時(shí)完成多種不同的輸入、輸出任務(wù)。由此可以 總結(jié)出,這種通過(guò)抽象接口消解應(yīng)用程序和類庫(kù)之間依賴關(guān)系的做法具有以下特點(diǎn):應(yīng)用程序調(diào)用類庫(kù)的抽象接口,依賴于類庫(kù)的抽象接口;具體的實(shí)現(xiàn)類派生自類庫(kù) 的抽象接口,也依賴于類庫(kù)的抽象接口。應(yīng)用程序和具體的類庫(kù)實(shí)現(xiàn)完全獨(dú)立,相互之間沒(méi)有直接的依賴關(guān)系,只要保持接 口類的穩(wěn)定,應(yīng)用程序和類庫(kù)的具體實(shí)現(xiàn)都可以獨(dú)立地發(fā)生變化。類庫(kù)完全可以獨(dú)立重用,應(yīng)用程序可以和任何一個(gè)實(shí)現(xiàn)了相同抽象接口的類庫(kù)協(xié)同 工作。一般情況下,由于類庫(kù)的設(shè)

12、計(jì)者并不知道應(yīng)用程序會(huì)如何使用類庫(kù),抽象接口大多由類 庫(kù)設(shè)計(jì)者根據(jù)自己設(shè)想的典型使用模式總結(jié)出來(lái),并保留一定的靈活度,以提供給應(yīng)用程序 的開發(fā)者使用。但還有另外一種情況。圖4是Martin Fowler在Reducing Coupling一文中使用的 一個(gè)例子Fowler 2001。其中,Domain包要使用數(shù)據(jù)庫(kù)包,即Domain包依賴于數(shù)據(jù)庫(kù)包。 為了隔離Domain包和數(shù)據(jù)庫(kù)包,可以引入一個(gè)Mapper包。如果在特定的情況下,我們希望 Domain包能夠被多次重用,而Mapper包可以隨時(shí)變化,那么,我們就必須防止Domain包 過(guò)分地依賴于Mapper包。這時(shí),可以由Domain包的設(shè)

13、計(jì)者總結(jié)出自己需要的抽象接口(如 Store),而由Mapper包的設(shè)計(jì)者來(lái)實(shí)現(xiàn)該抽象接口。這樣一來(lái),無(wú)論是在接口層面,還是 在實(shí)現(xiàn)層面,依賴關(guān)系都完全顛倒過(guò)來(lái)了。圖4完全倒置了的依賴關(guān)系控制反轉(zhuǎn)(Inversion of Control )前面描述的是應(yīng)用程序和類庫(kù)之間的依賴關(guān)系。如果我們開發(fā)的不是類庫(kù),而是框架系 統(tǒng),依賴關(guān)系就會(huì)更強(qiáng)烈一點(diǎn)。那么,該如何消解框架和應(yīng)用程序之間的依賴關(guān)系呢?道法自然第5章描述了框架和類庫(kù)之間的區(qū)別:“框架和類庫(kù)最重要的區(qū)別是:框架是一個(gè)半成品的應(yīng)用程序,而類庫(kù)只包含一系 列可被應(yīng)用程序調(diào)用的類?!邦悗?kù)給用戶提供了一系列可復(fù)用的類,這些類的設(shè)計(jì)都符合面向?qū)ο笤?/p>

14、則和模式。用 戶使用時(shí),可以創(chuàng)建這些類的實(shí)例,或從這些類中繼承出新的派生類,然后調(diào)用類中相應(yīng)的 功能。在這一過(guò)程中,類庫(kù)總是被動(dòng)地響應(yīng)用戶的調(diào)用請(qǐng)求?!翱蚣軇t會(huì)為某一特定目的實(shí)現(xiàn)一個(gè)基本的、可執(zhí)行的架構(gòu)??蚣苤幸呀?jīng)包含了應(yīng)用程 序從啟動(dòng)到運(yùn)行的主要流程,流程中那些無(wú)法預(yù)先確定的步驟留給用戶來(lái)實(shí)現(xiàn)。程序運(yùn)行時(shí), 框架系統(tǒng)自動(dòng)調(diào)用用戶實(shí)現(xiàn)的功能組件。這時(shí),框架系統(tǒng)的行為是主動(dòng)的?!拔覀兛梢哉f(shuō),類庫(kù)是死的,而框架是活的。應(yīng)用程序通過(guò)調(diào)用類庫(kù)來(lái)完成特定的功能, 而框架則通過(guò)調(diào)用應(yīng)用程序來(lái)實(shí)現(xiàn)整個(gè)操作流程??蚣苁强刂频怪迷瓌t的完美體現(xiàn)?!笨蚣芟到y(tǒng)的一個(gè)最好的例子就是圖形用戶界面(GUI)系統(tǒng)。一個(gè)簡(jiǎn)單的

15、,使用面向過(guò) 程的設(shè)計(jì)方法開發(fā)的GUI系統(tǒng)如圖5所示。從圖5中可以看出,應(yīng)用程序調(diào)用GUI框架中的CreateWindow()函數(shù)來(lái)創(chuàng)建窗口,在 這里,我們可以說(shuō)應(yīng)用程序依賴于GUI框架。但GUI框架并不了解該窗口接收到窗口消息后 應(yīng)該如何處理,這一點(diǎn)只有應(yīng)用程序最為清楚。因此,當(dāng)GUI框架需要發(fā)送窗口消息時(shí),又 必須調(diào)用應(yīng)用程序定義的某個(gè)特定的窗口函數(shù)(如上圖中的MyWindowProc)。這時(shí),GUI 框架又必須依賴于應(yīng)用程序。這是一個(gè)典型的雙向依賴關(guān)系。這種雙向依賴關(guān)系有一個(gè)非常 嚴(yán)重的缺陷:由于GUI框架調(diào)用了應(yīng)用程序中的某個(gè)特定函數(shù)(MyWindowProc), GUI框 架根本無(wú)法

16、獨(dú)立存在;換一個(gè)新的應(yīng)用程序,GUI框架多半就要做相應(yīng)的修改。因此,如何 消解框架系統(tǒng)對(duì)應(yīng)用程序的依賴關(guān)系是實(shí)現(xiàn)框架系統(tǒng)的關(guān)鍵。并非只有面向?qū)ο蟮姆椒ú拍芙鉀Q這一問(wèn)題。WIN32 API早就為我們提供了在面向過(guò)程的設(shè)計(jì)思路下解決類似問(wèn)題的范例。類WIN32的架構(gòu)模型如圖6所示。在圖6中,應(yīng)用程序調(diào)用CreateWindow()函數(shù)時(shí),要傳遞一個(gè)消息處理函數(shù)的指針給 GUI框架(對(duì)WIN32而言,我們?cè)谧?cè)窗口類時(shí)傳遞這一指針),GUI框架把該指針記錄在 窗口信息結(jié)構(gòu)中。需要發(fā)送窗口消息時(shí),GUI框架就通過(guò)該指針調(diào)用窗口函數(shù)。和圖5相 比,GUI框架仍然需要調(diào)用應(yīng)用程序,但這一調(diào)用從一個(gè)硬編碼的

17、函數(shù)調(diào)用變成了一個(gè)由應(yīng) 用程序事先注冊(cè)被調(diào)用對(duì)象的動(dòng)態(tài)調(diào)用。圖6用一條虛線表示這種動(dòng)態(tài)調(diào)用??梢钥闯?, 這種動(dòng)態(tài)的調(diào)用關(guān)系有一個(gè)非常大的好處:當(dāng)應(yīng)用程序發(fā)生變化時(shí),它可以自行改變框架系 統(tǒng)的調(diào)用目標(biāo),GUI框架無(wú)需隨之發(fā)生變化?,F(xiàn)在,我們可以說(shuō),雖然還存在著從GUI框架 到應(yīng)用程序的調(diào)用關(guān)系,但GUI框架已經(jīng)完全不再依賴于應(yīng)用程序了。這種動(dòng)態(tài)調(diào)用機(jī)制通 常也被稱為“回調(diào)函數(shù)”。在面向?qū)ο箢I(lǐng)域,“回調(diào)函數(shù)”的替代物就是“模板方法模式”,也就是“好萊塢原則 (不要調(diào)用我們,讓我們調(diào)用你)”。GUI框架的一個(gè)面向?qū)ο蟮膶?shí)現(xiàn)如圖7所示。Wf I! .人山*nd .佃圖?通過(guò)模械方法模式消解GUI框架登

18、應(yīng)用程序的依熬應(yīng)用程序7卷桀5*OeaiBV:ifiQ?w)主甫恩悔阪)主清恿慵環(huán)IH說(shuō)撲 I汩(GeMssatei . J (心.E訪I.?。簺_.Win :“臻3ES.-K3-* * H i*盤打客:;睥謬 Cr KeybaaclRea(Jer(), writer = n&w PnnterWnter();cpy(= (汨;c:k4r說(shuō) i(c = !i=r :ead( :J t= I of -Kirt: :i F?購(gòu)川)從圖8中可以看出,雖然Reader和Writer接口隔離了 “服務(wù)類”和具體的Reader和 Writer類,使它們之間的耦合降到了最小。但當(dāng)“服務(wù)類”創(chuàng)建具體的Reader

19、和Writer 對(duì)象時(shí),“服務(wù)類”還是和具體的Reader和Writer對(duì)象發(fā)生了依賴關(guān)系一一圖8中用藍(lán) 色的虛線描述了這種依賴關(guān)系。在這種情況下,如何實(shí)例化具體的Reader和Writer類,同時(shí)又盡量減少服務(wù)類對(duì)它們 的依賴,就是一個(gè)非常關(guān)鍵的問(wèn)題了。如果服務(wù)類位于應(yīng)用程序中,這一依賴關(guān)系對(duì)我們?cè)?成的影響還不算大。但當(dāng)“服務(wù)類”位于需要獨(dú)立發(fā)布的類庫(kù)中,它的代碼就不能隨著應(yīng)用 程序的變化而改變了。這也意味著,如果“服務(wù)類”過(guò)度依賴于具體的Reader和Writer 類,用戶就無(wú)法自行添加新的Reader和Writer的實(shí)現(xiàn)了。解決這一問(wèn)題的方法是“依賴注入”,即切斷“服務(wù)類”到具體的Re

20、ader和Writer 類之間的依賴關(guān)系,而由應(yīng)用程序來(lái)注入這一依賴關(guān)系。如圖9所示。圖3依賴注入在圖9中,“服務(wù)類”并不負(fù)責(zé)創(chuàng)建具體的Reader和Writer類的實(shí)例對(duì)象,而是由 應(yīng)用程序來(lái)創(chuàng)建。應(yīng)用程序創(chuàng)建“服務(wù)類”的實(shí)例對(duì)象時(shí),把具體的Reader和Write對(duì)象 的引用注入“服務(wù)類”內(nèi)部。這樣,“服務(wù)類”中的代碼就只和抽象接口相關(guān)的了。具體實(shí) 現(xiàn)代碼發(fā)生變化時(shí),“服務(wù)類”不會(huì)發(fā)生任何變化。添加新的實(shí)現(xiàn)時(shí),也只需要改變應(yīng)用程 序的代碼,就可以定義并使用新的Reader和Writer類,這種依賴注入方式通常也被稱為“構(gòu) 造器注入”。如果專門為Copy類抽象出一個(gè)注入接口,應(yīng)用程序通過(guò)接口注入依賴關(guān)系,這種注入 方式通常被稱為“接

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論