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元

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

                永久免费视频成人| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美视频在线播放| 久久久久久网址| 亚洲精品一区二区三区99| 国产精品一区在线观看你懂的| 久久一二三四| 午夜综合激情| 亚洲永久在线观看| 亚洲毛片av| 亚洲国产欧美一区二区三区同亚洲| 欧美性片在线观看| 欧美精品在线播放| 欧美福利电影在线观看| 久久精品国产96久久久香蕉| 亚洲一区美女视频在线观看免费| 亚洲精品久久久久久久久久久| 国产曰批免费观看久久久| 欧美日韩精品在线视频| 欧美成人亚洲成人日韩成人| 久久婷婷蜜乳一本欲蜜臀| 欧美尤物一区| 欧美一区不卡| 久久av二区| 欧美在线视频免费播放| 亚洲在线观看视频网站| 亚洲在线视频免费观看| 亚洲欧美高清| 小黄鸭视频精品导航| 亚洲欧美国产视频| 亚洲视频中文| 午夜日韩激情| 久久精品二区三区| 久久久久国产一区二区三区| 久久九九全国免费精品观看| 久久精品成人一区二区三区| 久久久久看片| 欧美成人午夜剧场免费观看| 欧美精品成人| 欧美日韩午夜激情| 国产麻豆视频精品| 激情亚洲网站| 最新国产拍偷乱拍精品 | 欧美国产日韩免费| 欧美精品亚洲| 国产精品久久久久久久久免费| 国产精品亚洲产品| 国产主播精品| 亚洲日韩中文字幕在线播放| 一本色道久久综合亚洲91| 亚洲视频1区2区| 欧美一区影院| 欧美高清视频在线播放| 国产精品国产福利国产秒拍| 国产一区欧美| 99re6热在线精品视频播放速度| 亚洲一区二区三区精品动漫| 久久成人资源| 欧美日韩第一区日日骚| 国产精品劲爆视频| 樱桃视频在线观看一区| 夜夜夜久久久| 久久免费黄色| 国产精品免费视频观看| 亚洲国产小视频| 午夜亚洲性色福利视频| 欧美极品色图| 激情91久久| 亚洲欧美日韩一区| 欧美激情一二三区| 黄色亚洲网站| 性亚洲最疯狂xxxx高清| 欧美日韩亚洲另类| 亚洲国产黄色| 久久青青草综合| 国产精品日韩电影| 日韩视频亚洲视频| 美女国产一区| 狠狠色狠狠色综合日日五| 亚洲综合精品一区二区| 欧美日韩综合视频| 亚洲国产精品黑人久久久| 久久成人资源| 国产欧美 在线欧美| 日韩视频永久免费| 欧美大胆a视频| 在线精品观看| 蜜桃精品一区二区三区| 国产综合久久| 久久国产精品久久w女人spa| 国产精品一区二区在线| 一区二区欧美激情| 欧美日韩一二区| 99视频国产精品免费观看| 欧美v国产在线一区二区三区| 激情久久五月| 六月天综合网| 亚洲国产日本| 欧美精品 日韩| 99精品免费| 国产精品成人一区| 亚洲一区久久| 国产精品视频免费观看| 亚洲欧美成人一区二区在线电影| 国产精品国色综合久久| 亚洲男同1069视频| 国产精品一区久久久久| 欧美一区三区二区在线观看| 国产丝袜一区二区| 久久久视频精品| 亚洲精品免费观看| 欧美日韩一区二区国产| 亚洲视频在线看| 国产一区二区在线免费观看 | 亚洲国产精品久久久久| 欧美激情视频给我| 99综合精品| 国产午夜精品久久久久久久| 久久久www| 亚洲日本激情| 国产精品国产精品国产专区不蜜| 亚洲女人小视频在线观看| 黑人操亚洲美女惩罚| 欧美~级网站不卡| 亚洲自啪免费| 亚洲精品久久久久久下一站| 国产精品久久一级| 久久人人爽国产| 亚洲午夜国产一区99re久久| 国内久久婷婷综合| 欧美日韩一区二区三区四区在线观看| 亚洲一区高清| 亚洲国产99| 国产日韩欧美综合在线| 欧美激情一区二区三区四区| 亚洲影院色无极综合| 亚洲福利免费| 国产一区 二区 三区一级| 欧美精品在线网站| 久久午夜色播影院免费高清| 亚洲一区二区成人| 亚洲国产美女| 国产一二精品视频| 欧美日韩综合精品| 欧美 日韩 国产在线| 久久黄色网页| 午夜精品久久久久久久99樱桃| 亚洲精品麻豆| 影音先锋亚洲电影| 国产区二精品视| 国产精品免费观看在线| 欧美日韩和欧美的一区二区| 老鸭窝91久久精品色噜噜导演| 亚洲欧美国产77777| 亚洲精品一区久久久久久| 一区二区三区在线观看视频| 国产日韩欧美麻豆| 国产精品午夜在线观看| 欧美色视频日本高清在线观看| 欧美国产在线视频| 欧美激情精品久久久久久大尺度 | 亚洲精品乱码久久久久久久久| 国产日韩欧美电影在线观看| 国产精品伦一区| 国产精品久久久爽爽爽麻豆色哟哟| 欧美xart系列在线观看| 久久这里只有| 欧美福利视频| 欧美精品激情| 欧美色综合天天久久综合精品| 欧美日韩精品一二三区| 欧美视频免费在线| 国产精品高精视频免费| 国产精品毛片va一区二区三区| 国产精品久久久久一区| 国产精品高潮粉嫩av| 国产精品视频yy9099| 国产精品蜜臀在线观看| 国产亚洲福利社区一区| 极品裸体白嫩激情啪啪国产精品| 狠狠色丁香婷婷综合| 亚洲福利国产精品| 一区二区黄色| 欧美一级视频| 久久亚洲图片| 欧美日韩在线播放一区| 国产精品h在线观看| 国产精品视频免费观看| 国产亚洲一本大道中文在线| 一区二区三区在线视频播放| 最新国产の精品合集bt伙计| 亚洲砖区区免费| 蜜桃av一区| 国产精品国产三级国产专区53 | 麻豆成人在线播放| 欧美美女福利视频| 国产欧美午夜| 99re6热只有精品免费观看| 亚洲自拍都市欧美小说| 麻豆freexxxx性91精品|
              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>