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;">

                      欧美高清一级片在线| 天堂av在线一区| 久久久久久久久久久久久久久99| 精品一区二区在线视频| 日韩欧美一区二区免费| 在线观看www91| 久久夜色精品国产噜噜av| 日本一区二区免费在线观看视频| 日日夜夜精品视频免费| 色妞www精品视频| 亚洲精品成人精品456| 精品视频免费在线| 日韩一区二区三区在线观看| 欧美激情一区二区三区不卡 | 中文字幕亚洲在| 一级特黄大欧美久久久| 日韩电影在线一区| 国产一区二区精品久久91| 紧缚奴在线一区二区三区| 在线观看成人免费视频| 国产亚洲欧美在线| 国产东北露脸精品视频| 久久伊人蜜桃av一区二区| 麻豆免费看一区二区三区| 日韩精品在线网站| 色吧成人激情小说| 中文一区一区三区高中清不卡| 亚洲国产成人自拍| 美腿丝袜亚洲色图| 欧美精品v国产精品v日韩精品| 《视频一区视频二区| 狠狠色丁香久久婷婷综合丁香| 欧美日韩一区二区三区四区五区 | 精品国产自在久精品国产| 亚洲精品成人悠悠色影视| aaa亚洲精品一二三区| 久久久亚洲综合| 激情综合色丁香一区二区| 欧美一区二区三区四区视频| 亚洲mv在线观看| 欧美日韩精品久久久| 一区二区三区视频在线看| 97久久超碰精品国产| 国产精品日产欧美久久久久| 成人做爰69片免费看网站| 亚洲日本韩国一区| 欧美妇女性影城| 激情深爱一区二区| 亚洲一区二区三区三| 7777精品伊人久久久大香线蕉| ww亚洲ww在线观看国产| 欧美国产亚洲另类动漫| 欧洲亚洲精品在线| 丁香啪啪综合成人亚洲小说 | 日本麻豆一区二区三区视频| 天堂久久久久va久久久久| 成人自拍视频在线观看| 日本不卡一区二区三区高清视频| 色哟哟精品一区| 亚洲国产色一区| 欧美剧情片在线观看| 日本美女一区二区三区| 精品毛片乱码1区2区3区| 韩国中文字幕2020精品| 久久精子c满五个校花| 成人av午夜电影| 亚洲一区二区三区不卡国产欧美| 欧美一级二级在线观看| 一区二区三区欧美| 91超碰这里只有精品国产| 国产麻豆9l精品三级站| 国产精品的网站| 欧美男同性恋视频网站| 狠狠色丁香久久婷婷综合丁香| 国产精品免费久久久久| 欧美色图在线观看| 国产一区二区三区四区五区入口| 中文字幕中文乱码欧美一区二区| 欧美性受极品xxxx喷水| 韩国v欧美v日本v亚洲v| 亚洲欧洲日韩av| 欧美成人国产一区二区| 99久久精品久久久久久清纯| 一区二区免费视频| 国产偷v国产偷v亚洲高清| 欧美丝袜丝交足nylons图片| 国产在线精品一区二区三区不卡| 亚洲欧洲综合另类| 精品国产一区a| 欧美性一级生活| 成人激情开心网| 日韩电影网1区2区| 最近中文字幕一区二区三区| 欧美一区二区在线视频| 97久久人人超碰| 亚洲一区二区三区四区在线观看| 丝袜美腿亚洲综合| 99国产精品国产精品久久| 欧美成人乱码一区二区三区| 怡红院av一区二区三区| 精品一区二区三区的国产在线播放| 国产精品一区二区三区99 | 视频在线在亚洲| 懂色av一区二区三区免费看| 国产亚洲精品7777| wwwwxxxxx欧美| 久久精品欧美日韩精品 | 日本美女一区二区三区| 成人欧美一区二区三区小说 | 制服丝袜一区二区三区| 97国产精品videossex| 国产麻豆欧美日韩一区| 久久成人免费日本黄色| 亚洲风情在线资源站| 亚洲免费观看视频| 亚洲欧美在线另类| 国产精品国产三级国产三级人妇 | 91精品国产91久久久久久一区二区| 成人开心网精品视频| 国内外精品视频| 久久精品二区亚洲w码| 日本免费新一区视频| 天天综合天天综合色| 亚洲综合在线五月| 一级特黄大欧美久久久| 又紧又大又爽精品一区二区| 亚洲婷婷综合色高清在线| 国产精品久久久久久亚洲伦| 国产精品久久久一区麻豆最新章节| 亚洲精品一区在线观看| 久久久久久久久蜜桃| 久久久不卡网国产精品一区| 久久在线观看免费| 国产午夜精品久久| 综合婷婷亚洲小说| 亚洲视频电影在线| 亚洲一区二区3| 日韩电影在线一区二区| 国产精品99久久久久久有的能看| 国产日韩欧美麻豆| 精品久久久久久亚洲综合网| 国产精品456| 亚洲欧美激情视频在线观看一区二区三区 | 美女mm1313爽爽久久久蜜臀| 欧美r级电影在线观看| 色噜噜久久综合| 国产盗摄精品一区二区三区在线| 一区二区三区鲁丝不卡| 国产精品久久久久一区| 久久免费偷拍视频| 欧美精品乱码久久久久久| 97久久超碰国产精品电影| 日韩成人av影视| 久久亚洲精华国产精华液| 免费在线看一区| 国内精品自线一区二区三区视频| 色哟哟亚洲精品| 裸体在线国模精品偷拍| 青青草国产精品97视觉盛宴| 国产一区二区三区精品欧美日韩一区二区三区 | 精品国偷自产国产一区| av在线一区二区三区| 国产成人精品免费一区二区| 国产在线麻豆精品观看| 国产在线精品视频| 成人综合婷婷国产精品久久| 99re成人精品视频| 欧美性大战久久| 91精品国产高清一区二区三区| 成人午夜激情在线| 97久久超碰精品国产| 3atv一区二区三区| 久久无码av三级| 欧美亚洲国产一区二区三区 | 欧美激情综合五月色丁香小说| 亚洲人成网站色在线观看| 美女任你摸久久 | 青娱乐精品视频| 成人精品在线视频观看| 7777精品伊人久久久大香线蕉超级流畅 | 亚洲免费观看高清完整版在线观看 | 午夜av一区二区三区| 国产麻豆精品在线观看| 欧美手机在线视频| 国产精品久久免费看| 在线91免费看| 久久精品一区二区| 日本不卡在线视频| 国产一区999| 日韩免费看的电影| 国产精品乱码妇女bbbb| 亚洲国产中文字幕| 成人精品国产一区二区4080| 欧美乱熟臀69xxxxxx| 亚洲欧美一区二区三区孕妇| 国产在线精品一区二区不卡了| 在线视频国产一区| 日日嗨av一区二区三区四区| 国产精品天美传媒沈樵| 日韩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>