11111111111
知識共享平臺
知識共享平臺

討教大學平臺

  • 首頁
  • 免費課
  • 精品課
  • 討教題庫
  • 企業(yè)服務(wù)

    hot

  • 下載APP
  • 證書查詢
  • 關(guān)于我們
我問
討教號
搜索
消息
  • 我的文章

    我的關(guān)注

    我的問答

    我的秘密

    我的評論

    我的訂閱

    我的打賞

    我的錢包

    我的通知

    我的設(shè)置

    退出登錄

  • ×

    登錄

    討教 | 通行證

    登錄
    立即注冊
    忘記密碼?
    使用微信登錄

    提問 ×

    寫下你的問題,準確的表述更容易得到答案

    類型話題

    選擇支付方式
    您的討教幣 111 付費金額

    国产第一亚洲_浪货一天不做就难受呀_欧洲视频在线观看_亚洲精品一区二区三区美女

    <cite id="0eakq"><center id="0eakq"></center></cite>
    <bdo id="0eakq"></bdo>
    <rt id="0eakq"></rt>
    • <rt id="0eakq"></rt>
      <code id="0eakq"><tr id="0eakq"></tr></code>
      <tfoot id="0eakq"><delect id="0eakq"></delect></tfoot>
      <table id="0eakq"><wbr id="0eakq"></wbr></table>
      • <small id="0eakq"><center id="0eakq"></center></small>
          <table id="0eakq"></table>
          <li id="0eakq"></li>
          <li id="0eakq"><tbody id="0eakq"></tbody></li>

          Java中的控制(耦合)反轉(zhuǎn)

          JAVA葵花寶典
          2019-06-19 17:54:16
          16篇 作品
          2137 總閱讀量

          什么是控制反轉(zhuǎn)?什么是依賴注入?這些類型的問題通常會遇到代碼示例,模糊解釋以及StackOverflow上標識為“ 低質(zhì)量答案 ”的問題。

          我們使用控制反轉(zhuǎn)和依賴注入,并經(jīng)常將其作為構(gòu)建應(yīng)用程序的正確方法。然而,我們無法清晰地闡明原因!

          原因是我們還沒有清楚地確定控制是什么。一旦我們理解了我們正在反轉(zhuǎn)的內(nèi)容,控制反轉(zhuǎn)與依賴注入的概念實際上并不是要問的問題。它實際上變成了以下內(nèi)容:

          控制反轉(zhuǎn) = 依賴(狀態(tài))注入 + 線程注入 + 連續(xù)(函數(shù))注入

          為了解釋這一點,我們來寫一些代碼。是的,使用代碼來解釋控制反轉(zhuǎn)的明顯問題正在重復,但請耐心等待,答案一直在你眼前。

          一個明確使用控制反轉(zhuǎn)/依賴注入的模式是存儲庫模式,來避免繞過連接。而不是以下:

          1. public class NoDependencyInjectionRepository implements Repository<Entity> {


          2. public void save(Entity entity, Connection connection) throws SQLException {

          3. // Use connection to save entity to database

          4. }

          5. }

          依賴注入允許將存儲庫重新實現(xiàn)為:

          1. public class DependencyInjectionRepository implements Repository<Entity> {

          2. @Inject Connection connection;

          3. public void save(Entity entity) throws SQLException {

          4. // Use injected connection to save entity to database

          5. }

          6. }

          現(xiàn)在,你看到我們剛剛解決的問題了嗎?

          如果您正在考慮“我現(xiàn)在可以更改 connection 來使用REST調(diào)用” ,這一切都可以靈活改變,那么您就會很接近這個問題。

          要查看問題是否已解決,請不要查看實現(xiàn)類。相反,看看接口。客戶端調(diào)用代碼已經(jīng)從:

          1. repository.save(entity, connection);

          變?yōu)橐韵聝?nèi)容:

          1. repository.save(entity);

          我們已經(jīng)移除了客戶端代碼的耦合,以提供一個 connection 在調(diào)用方法上。通過刪除耦合,我們可以替換存儲庫的不同實現(xiàn)(再次,無聊的代碼,但請忍受我):

          1. public class WebServiceRepository implements Repository<Entity> {

          2. @Inject WebClient client;

          3. public void save(Entity entity) {

          4. // Use injected web client to save entity

          5. }

          6. }

          客戶端能夠繼續(xù)調(diào)用方法:

          1. repository.save(entity);

          客戶端不知道存儲庫現(xiàn)在調(diào)用微服務(wù)來保存實體而不是直接與數(shù)據(jù)庫通信。(實際上,客戶已經(jīng)知道,但我們很快就會談到這一點。)

          因此,將此問題提升到關(guān)于該方法的抽象級別:

          1. R method(P1 p1, P2 p2) throws E1, E2

          2. // with dependency injection becomes

          3. @Inject P1 p1;

          4. @Inject P2 p2;

          5. R method() throws E1, E2

          通過依賴注入消除了客戶端為該方法提供參數(shù)的耦合。

          現(xiàn)在,你看到耦合的其他四個問題了嗎?

          在這一點上,我警告你,一旦我向你展示耦合問題,你將永遠不會再看同樣的代碼了。 這是矩陣中我要問你是否想要紅色或藍色的要點。一旦我向你展示這個問題真正的兔子洞有多遠,就沒有回頭了 - 實際上沒有必要進行重構(gòu),而且在建模邏輯和計算機科學的基礎(chǔ)知識方面存在問題(好的,大的聲明,但請繼續(xù)閱讀 - 我不會把它放在任何其他方式)。

          所以,你選擇了紅點。

          讓我們?yōu)槟阕龊脺蕚洹?/p>

          為了識別四個額外的耦合問題,讓我們再看一下抽象方法:

          1. @Inject P1 p1;

          2. @Inject P2 p2;

          3. R method() throws E1, E2

          4. // and invoking it

          5. try {

          6. R result = object.method();

          7. } catch (E1 | E2 ex) {

          8. // handle exception

          9. }

          什么是客戶端代碼耦合?

          • 返回類型

          • 方法名稱

          • 處理異常

          • 提供給該方法的線程

          依賴注入允許我更改方法所需的對象,而無需更改調(diào)用方法的客戶端代碼。但是,如果我想通過以下方式更改我的實現(xiàn)方法:

          • 更改其返回類型

          • 修改它的名稱

          • 拋出一個新的異常(在上面的交換到微服務(wù)存儲庫的情況下,拋出HTTP異常而不是SQL異常)

          • 使用不同的線程(池)執(zhí)行方法而不是客戶端調(diào)用提供的線程

          這涉及“ 重構(gòu) ”我的方法的所有客戶端代碼。當實現(xiàn)具有實際執(zhí)行功能的艱巨任務(wù)時,為什么調(diào)用者要求耦合?我們實際上應(yīng)該反轉(zhuǎn)耦合,以便實現(xiàn)可以指示方法簽名(而不是調(diào)用者)。

          你可能就像Neo在黑客帝國中所做的那樣“哼”一下嗎?讓實現(xiàn)定義他們的方法簽名?但是,不是覆蓋和實現(xiàn)抽象方法簽名定義的整個OO原則嗎?這樣只會導致更混亂,因為如果它的返回類型,名稱,異常,參數(shù)隨著實現(xiàn)的發(fā)展而不斷變化,我如何調(diào)用該方法?

          簡單。你已經(jīng)知道了模式。你只是沒有看到他們一起使用,他們的總和比他們的部分更強大。

          因此,讓我們遍歷方法的五個耦合點(返回類型,方法名稱,參數(shù),異常,調(diào)用線程)并將它們分離。

          我們已經(jīng)看到依賴注入刪除了客戶端的參數(shù)耦合,所以一個個向下。

          接下來,讓我們處理方法名稱。

          方法名稱解耦

          許多語言(包括Java lambdas)允許或具有該語言的一等公民的功能。通過創(chuàng)建對方法的函數(shù)引用,我們不再需要知道方法名稱來調(diào)用該方法:

          1. Runnable f1 = () -> object.method();

          2. // Client call now decoupled from method name

          3. f1.run()

          我們現(xiàn)在甚至可以通過依賴注入傳遞方法的不同實現(xiàn):

          1. @Inject Runnable f1;

          2. void clientCode() {

          3. f1.run(); // to invoke the injected method

          4. }

          好的,這是一些額外的代碼,沒有太大的額外價值。但是,再次,忍受我。我們已將方法的名稱與調(diào)用者分離。

          接下來,讓我們解決方法中的異常。

          方法異常解耦

          通過使用上面的注入函數(shù)技術(shù),我們注入函數(shù)來處理異常:

          1. Runnable f1 = () -> {

          2. @Inject Consumer<E1> h1;

          3. @Inject Consumer<E2> h2;

          4. try {

          5. object.method();

          6. } catch (E1 e1) {

          7. h1.accept(e1);

          8. } catch (E2 e2) {

          9. h2.accept(e2);

          10. }

          11. }

          12. // 注意:上面是用于標識概念的抽象偽代碼(我們將很快編譯代碼)

          現(xiàn)在,異常不再是客戶端調(diào)用者的問題。注入的方法現(xiàn)在處理將調(diào)用者與必須處理異常分離的異常。

          接下來,讓我們處理調(diào)用線程。

          方法的調(diào)用線程解耦

          通過使用異步函數(shù)簽名并注入Executor,我們可以將調(diào)用實現(xiàn)方法的線程與調(diào)用者提供的線程分離:

          1. Runnable f1 = () -> {

          2. @Inject Executor executor;

          3. executor.execute(() -> {

          4. object.method();

          5. });

          6. }

          通過注入適當?shù)?Executor,我們可以使用我們需要的任何線程池調(diào)用的實現(xiàn)方法。要重用客戶端的調(diào)用線程,我們只需要同步Exectutor:

          1. Executor synchronous = (runnable) -> runnable.run();

          所以現(xiàn)在,我們可以解耦一個線程,從調(diào)用代碼的線程執(zhí)行實現(xiàn)方法。

          但是沒有返回值,我們?nèi)绾卧诜椒ㄖg傳遞狀態(tài)(對象)?讓我們將它們與依賴注入結(jié)合在一起。

          控制(耦合)反轉(zhuǎn)

          讓我們將上述模式與依賴注入相結(jié)合,得到ManagedFunction:

          1. public interface ManagedFunction {

          2. void run();

          3. }

          4. public class ManagedFunctionImpl implements ManagedFunction {

          5. @Inject P1 p1;

          6. @Inject P2 p2;

          7. @Inject ManagedFunction f1; // other method implementations to invoke

          8. @Inject ManagedFunction f2;

          9. @Inject Consumer<E1> h1;

          10. @Inject Consumer<E2> h2;

          11. @Inject Executor executor;

          12. @Override

          13. public void run() {

          14. executor.execute(() -> {

          15. try {

          16. implementation(p1, p2, f1, f2);

          17. } catch (E1 e1) {

          18. h1.accept(e1);

          19. } catch (E2 e2) {

          20. h2.accept(e2);

          21. });

          22. }

          23. private void implementation(

          24. P1 p1, P2 p2,

          25. ManagedFunction f1, ManagedFunction f2

          26. ) throws E1, E2 {

          27. // use dependency inject objects p1, p2

          28. // invoke other methods via f1, f2

          29. // allow throwing exceptions E1, E2

          30. }

          31. }

          好的,這里有很多東西,但它只是上面的模式結(jié)合在一起。客戶端代碼現(xiàn)在完全與方法實現(xiàn)分離,因為它只運行:

          1. @Inject ManagedFunction function;

          2. public void clientCode() {

          3. function.run();

          4. }

          現(xiàn)在可以自由更改實現(xiàn)方法,而不會影響客戶端調(diào)用代碼:

          • 方法沒有返回類型(一般的限制可以使用void,但是異步代碼是必需的)

          • 實現(xiàn)方法名稱可能會更改,因為它包含在 ManagedFunction.run()

          • 不再需要參數(shù)ManagedFunction。這些是依賴注入的,允許實現(xiàn)方法選擇它需要哪些參數(shù)(對象)

          • 異常由注入的Consumers處理。實現(xiàn)方法現(xiàn)在可以規(guī)定它拋出的異常,只需要Consumers 注入不同的異常 。客戶端調(diào)用代碼不需要知道實現(xiàn)方法,現(xiàn)在可以自定義拋出 HTTPException 而不是 SQLException 。此外, Consumers 實際上可以通過ManagedFunctions 注入異常來實現(xiàn) 。

          • 注入Executor 允許實現(xiàn)方法通過指定注入的Executor來指示其執(zhí)行的線程 。這可能導致重用客戶端的調(diào)用線程或讓實現(xiàn)由單獨的線程或線程池運行

          現(xiàn)在,通過其調(diào)用者的方法的所有五個耦合點都是分離的。

          我們實際上已經(jīng)“對耦合進行了反向控制”。換句話說,客戶端調(diào)用者不再指定實現(xiàn)方法可以命名的內(nèi)容,用作參數(shù),拋出異常,使用哪個線程等。耦合的控制被反轉(zhuǎn),以便實現(xiàn)方法可以決定它耦合到什么指定它是必需的注射。

          此外,由于調(diào)用者沒有耦合,因此不需要重構(gòu)代碼。實現(xiàn)發(fā)生變化,然后將其耦合(注入)配置到系統(tǒng)的其余部分。客戶端調(diào)用代碼不再需要重構(gòu)。

          因此,實際上,依賴注入只解決了方法耦合問題的1/5。對于僅解決20%問題非常成功的事情,它確實顯示了該方法的耦合問題究竟有多少。

          實現(xiàn)上述模式將創(chuàng)建比您的系統(tǒng)中更多的代碼。這就是為什么開源框架OfficeFloor是控制框架的“真正”反轉(zhuǎn),并且已經(jīng)整合在一起以減輕此代碼的負擔。這是上述概念中的一個實驗,以查看真實系統(tǒng)是否更容易構(gòu)建和維護,具有“真正的”控制反轉(zhuǎn)。

          摘要

          因此,下次你遇到Refactor Button / Command時,意識到這是通過每次編寫代碼時一直盯著我們的方法的耦合引起的。

          真的,為什么我們有方法簽名?這是因為線程堆棧。我們需要將內(nèi)存加載到線程堆棧中,并且方法簽名遵循計算機的行為。但是,在現(xiàn)實世界中,對象之間行為的建模不提供線程堆棧。對象都是通過很小的接觸點松耦合 - 而不是由該方法施加的五個耦合方面。

          此外,在計算中,我們努力實現(xiàn)低耦合和高內(nèi)聚。有人可能會提出一個案例,來對比ManagedFunctions,方法是:

          • 高耦合:方法有五個方面耦合到客戶端調(diào)用代碼

          • 低內(nèi)聚:隨著方法處理異常和返回類型開始模糊方法的責任隨著時間的推移,持續(xù)變化和快捷方式會迅速降低方法實施的凝聚力,開始處理超出其責任的邏輯

          由于我們力求低耦合和高內(nèi)聚,我們最基本的構(gòu)建塊( method 和 function)可能實際上違背了我們最核心的編程原則。

          本網(wǎng)站內(nèi)容僅代表作者本人的觀點,不代表本網(wǎng)站的觀點和看法,與本網(wǎng)站立場無關(guān),如有侵權(quán)請聯(lián)系討教。
          給作者打賞,鼓勵TA抓緊創(chuàng)作
          0人打賞金額
          JAVA葵花寶典
          16篇 作品
          2137 總閱讀量
          評論
          您可能感興趣的文章

          項目管理服務(wù)模式

          敏捷項目管理與傳統(tǒng)項目管理比較

          項目管理的特點

          PMO是什么?是管項目經(jīng)理的嘛?

          項目經(jīng)理必須關(guān)注的開會十大關(guān)鍵問題!

          項目的組成要素

          熱門話題 更多話題
          精益生產(chǎn) 質(zhì)量管理 智能制造
          職場效率 項目管理 討教
          AI 大數(shù)據(jù) 六西格瑪
          ×

          給作者打賞,鼓勵TA抓緊創(chuàng)作!

          選擇支付方式
          選擇打賞金額
          注:打賞的收益歸作者,非平臺

          微信掃描支付

          打賞金額: 1元

          ×

          給作者打賞,鼓勵TA抓緊創(chuàng)作!

          您的討教幣
          填寫您打賞討教幣數(shù)量
          輸入密碼

          111

          注:打賞的收益歸作者,非平臺

          微信掃描支付

          打賞金額: 1元

          国产第一亚洲_浪货一天不做就难受呀_欧洲视频在线观看_亚洲精品一区二区三区美女

                9000px;">

                      日韩高清不卡一区二区| 717成人午夜免费福利电影| 日韩一区二区三区电影 | voyeur盗摄精品| 亚洲综合无码一区二区| 久久亚洲欧美国产精品乐播 | 国产精品国产三级国产有无不卡 | 国产成人亚洲精品青草天美| 久久九九久久九九| caoporen国产精品视频| 亚洲综合色丁香婷婷六月图片| 欧美精品久久99| 91麻豆福利精品推荐| 91久久精品一区二区三区| 蜜臀国产一区二区三区在线播放| 亚洲欧美在线aaa| 五月婷婷综合在线| 国产一区二区三区在线观看精品| av亚洲精华国产精华精| 欧美三片在线视频观看| 国产日韩欧美电影| 亚洲国产另类精品专区| 国产一区二区精品久久99| 91在线你懂得| 欧美一区二区在线看| 国产三区在线成人av| 丝袜亚洲另类欧美| 91蝌蚪国产九色| 午夜伊人狠狠久久| 亚洲第一精品在线| 粉嫩在线一区二区三区视频| 欧美视频一区二区三区在线观看| 欧美精品一区视频| 日韩在线观看一区二区| 不卡视频在线观看| 欧美肥大bbwbbw高潮| 亚洲男同1069视频| 美女一区二区在线观看| 另类调教123区| 波多野结衣中文字幕一区二区三区| 欧美激情综合网| 日本欧美在线观看| 欧美精品一二三区| 午夜精品久久久久久久久久 | 日韩一区二区免费电影| 亚洲国产精品一区二区久久 | 欧美精品aⅴ在线视频| 亚洲乱码国产乱码精品精可以看| 国产一区二区三区电影在线观看 | 成人综合在线视频| 日韩小视频在线观看专区| 午夜不卡av免费| 欧美一级一区二区| 一区二区三区不卡视频在线观看| 精品午夜久久福利影院| 欧美精品第一页| 亚洲美女屁股眼交| 国产成人夜色高潮福利影视| 欧洲生活片亚洲生活在线观看| 精品国产91九色蝌蚪| 亚洲一区二区在线播放相泽| 青青草97国产精品免费观看| 国产成人免费在线视频| 欧美本精品男人aⅴ天堂| 日韩高清电影一区| 欧美一区二区三区男人的天堂| 国产精品毛片久久久久久| 国产一区 二区 三区一级| 91精品免费在线观看| 无码av中文一区二区三区桃花岛| 99精品桃花视频在线观看| 亚洲欧美激情小说另类| 欧美日韩一区国产| 蜜臀精品一区二区三区在线观看| 美女一区二区视频| 欧美mv日韩mv国产网站| 精品久久久久久综合日本欧美| 亚洲成人自拍偷拍| 久久综合久色欧美综合狠狠| 欧美美女网站色| 一区二区国产视频| 欧美人与z0zoxxxx视频| 成人免费看视频| 性做久久久久久免费观看| 中文一区二区完整视频在线观看| 粉嫩欧美一区二区三区高清影视| 日韩欧美精品在线视频| 另类成人小视频在线| 久久久亚洲精品石原莉奈 | 午夜精品影院在线观看| 91精品中文字幕一区二区三区| 成人性生交大片免费看中文| 日本va欧美va欧美va精品| 国产精品看片你懂得| 久久精品人人做| 久久久噜噜噜久噜久久综合| 51精品视频一区二区三区| 欧美日韩国产另类一区| 欧美在线观看一区二区| 日本道色综合久久| 欧美日韩亚洲不卡| 在线观看日韩电影| 成人av手机在线观看| 91网站在线观看视频| 成人美女视频在线观看18| 高清视频一区二区| 成人免费视频网站在线观看| 国产一区 二区 三区一级| 亚洲h动漫在线| 亚洲成在人线免费| 亚洲欧美日韩在线| 精品sm捆绑视频| 久久久天堂av| 亚洲视频综合在线| 自拍偷拍亚洲激情| 亚洲不卡av一区二区三区| 国产美女娇喘av呻吟久久| 色哟哟国产精品| 国产精品天美传媒沈樵| 日本vs亚洲vs韩国一区三区二区 | 欧美日韩中文字幕精品| 国产精品不卡一区二区三区| 亚洲日本在线天堂| 蜜臀国产一区二区三区在线播放| 国产成人无遮挡在线视频| 懂色av一区二区三区免费观看| 欧洲国产伦久久久久久久| 26uuu国产电影一区二区| 亚洲国产精品影院| 免费观看久久久4p| 亚洲精品在线电影| 一区二区三区四区亚洲| 亚洲午夜激情av| 福利91精品一区二区三区| 色综合色狠狠综合色| 精品少妇一区二区三区视频免付费 | 欧美精品一区二区高清在线观看 | 国产综合久久久久久鬼色| 午夜不卡av免费| 日韩午夜在线观看| 久久福利资源站| 国产精品黄色在线观看| 奇米影视在线99精品| 最新成人av在线| 亚洲观看高清完整版在线观看| 国产激情一区二区三区四区| 中文字幕成人网| 91在线观看成人| 亚洲综合成人在线| 91麻豆精品91久久久久久清纯| 天天亚洲美女在线视频| 久久久精品日韩欧美| www.色精品| 青青草成人在线观看| 国产色产综合产在线视频| 欧美三级资源在线| 国内成人精品2018免费看| 国产日产欧美一区| 欧美日韩你懂得| 日本午夜一区二区| 亚洲欧洲av另类| 国产乱国产乱300精品| 中文字幕国产一区| 尤物av一区二区| 91丨porny丨在线| 欧美日韩国产a| 久久久夜色精品亚洲| 日韩有码一区二区三区| 国产激情一区二区三区四区| 91在线高清观看| 久久亚洲一级片| 亚洲大片免费看| 国产成人精品三级麻豆| 在线观看一区不卡| 精品999久久久| 国产精品欧美久久久久一区二区| 亚洲一区二区三区四区不卡| 丁香天五香天堂综合| 欧美肥妇bbw| 亚洲综合成人在线视频| 欧美日韩一本到| 亚洲一区在线免费观看| 91在线观看美女| 日韩美女视频一区二区| 国产一区二区三区免费在线观看| 国产精品综合在线视频| 91.com在线观看| 99久久免费视频.com| 欧美老女人第四色| 亚洲精品福利视频网站| 国产成人免费网站| 久久久五月婷婷| 亚洲一区二区三区视频在线| 精品一区二区三区的国产在线播放 | 国产成人亚洲精品狼色在线| 久久99国产精品免费网站| 亚洲视频 欧洲视频| 欧美成人精品高清在线播放| 亚洲一区二区三区四区五区中文| av一区二区三区黑人|
                    1. <rt id="00ssq"></rt>
                        <cite id="00ssq"></cite>
                          <rt id="00ssq"></rt>
                          <li id="00ssq"><source id="00ssq"></source></li>
                          <abbr id="00ssq"><tbody id="00ssq"></tbody></abbr>
                          <center id="00ssq"></center>
                          <tfoot id="00ssq"><delect id="00ssq"></delect></tfoot>