成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何利用迪米特法則實(shí)現(xiàn)“高內(nèi)聚、低耦合”?

開(kāi)發(fā) 前端
盡管還是要往Demo1的構(gòu)造器傳入包含序列化和反序列化的Serialization實(shí)現(xiàn)類(lèi),但依賴(lài)的Serializable接口只包含序列化操作,Demo1無(wú)法使用Serialization類(lèi)中的反序列化接口,對(duì)反序列化操作無(wú)感知,符合迪米特法則的“依賴(lài)有限接口”。

1.何為“高內(nèi)聚、低耦合”?

“高內(nèi)聚、低耦合”能有效地提高代碼可讀性、可維護(hù)性,縮小功能改動(dòng)導(dǎo)致的代碼改動(dòng)范圍。很多設(shè)計(jì)原則也都以實(shí)現(xiàn)代碼“高內(nèi)聚、低耦合”為目的,比如:

  • 單一職責(zé)原則
  • 面向接口,而非面向?qū)崿F(xiàn)來(lái)編程

“高內(nèi)聚、低耦合”是個(gè)通用設(shè)計(jì)思想,可指導(dǎo):

  • 不同粒度代碼的設(shè)計(jì)與開(kāi)發(fā)

如系統(tǒng)、模塊、類(lèi),甚至函數(shù)

  • 不同開(kāi)發(fā)場(chǎng)景
  • 如微服務(wù)、框架、組件、類(lèi)庫(kù)等

本文主要圍繞以“類(lèi)”作為該設(shè)計(jì)思想的應(yīng)用對(duì)象。

  • “高內(nèi)聚”,指導(dǎo)類(lèi)本身的設(shè)計(jì)
  • “低耦合”,指導(dǎo)類(lèi)與類(lèi)之間依賴(lài)關(guān)系的設(shè)計(jì)

二者并非完全獨(dú)立,高內(nèi)聚有助于低耦合,低耦合又需要高內(nèi)聚的支持。

1.1 高內(nèi)聚

  • 相近的功能,應(yīng)放到同一個(gè)類(lèi)
  • 不相近的功能,不要放到同一個(gè)類(lèi)

相近的功能往往會(huì)被同時(shí)修改,放到同一類(lèi)中,修改會(huì)比較集中,代碼易維護(hù)。單一職責(zé)原則就是實(shí)現(xiàn)代碼高內(nèi)聚非常有效的設(shè)計(jì)原則。

1.2 低耦合

在代碼中,類(lèi)與類(lèi)之間的依賴(lài)關(guān)系簡(jiǎn)單清晰。

即使兩個(gè)類(lèi)有依賴(lài)關(guān)系,一個(gè)類(lèi)的代碼改動(dòng)不會(huì)或很少會(huì)導(dǎo)致依賴(lài)類(lèi)的代碼改動(dòng)。依賴(lài)注入、接口隔離、面向接口編程及迪米特法則都是為實(shí)現(xiàn)低耦合。

1.3 “內(nèi)聚”和“耦合”的關(guān)系

左邊代碼結(jié)構(gòu)是“高內(nèi)聚、低耦合”;右邊“低內(nèi)聚、緊耦合”:

左邊的代碼設(shè)計(jì):

類(lèi)的粒度較小,每個(gè)類(lèi)的職責(zé)都比較單一。相近功能都放到了一個(gè)類(lèi),不相近功能分割到多個(gè)類(lèi)。這樣類(lèi)更加獨(dú)立,代碼內(nèi)聚性更好。

因?yàn)槁氊?zé)單一,所以每個(gè)類(lèi)被依賴(lài)的類(lèi)就會(huì)比較少,代碼低耦合。一個(gè)類(lèi)的修改,只會(huì)影響到一個(gè)依賴(lài)類(lèi)的代碼改動(dòng)。只需要測(cè)試這一個(gè)依賴(lài)類(lèi)是否還能正常工作即可。

右邊代碼設(shè)計(jì):

類(lèi)粒度比較大,低內(nèi)聚,功能大而全,不相近的功能放到了一個(gè)類(lèi)中。導(dǎo)致很多其他類(lèi)都依賴(lài)該類(lèi)。修改這個(gè)類(lèi)的某功能代碼時(shí),會(huì)影響依賴(lài)它的多個(gè)類(lèi)。我們需要測(cè)試這三個(gè)依賴(lài)類(lèi),是否還能正常工作,“牽一發(fā)而動(dòng)全身”。

2.迪米特法則

Law of Demeter,LOD,從名字看不出這是個(gè)啥。它還有另外一個(gè)名字:最小知識(shí)原則。

The Least Knowledge Principle:Each unit should have only limited knowledge about other units: only units “closely” related to the current unit. Or: Each unit should only talk to its friends; Don’t talk to strangers.

每個(gè)模塊都只應(yīng)該了解那些與它關(guān)系密切的模塊(units: only units “closely” related to the current unit)的有限知識(shí)(knowledge)?;蛘哒f(shuō),每個(gè)模塊只和自己的朋友“說(shuō)話(huà)”(talk),不和陌生人“說(shuō)話(huà)”(tal?k)。

結(jié)合實(shí)際,定義描述中的“模塊”替換成“類(lèi)”:

  • 不該有直接依賴(lài)關(guān)系的類(lèi)之間,不要有依賴(lài)
  • 有依賴(lài)關(guān)系的類(lèi)之間,盡量只依賴(lài)必要的接口(“有限知識(shí)”)

所以,迪米特法則其實(shí)包含兩部分,下面用兩個(gè)案例分別解讀。

3.案例

3.1 不該有直接依賴(lài)關(guān)系的類(lèi)之間,不要有依賴(lài)

簡(jiǎn)化的搜索引擎爬取網(wǎng)頁(yè),包含如下主要類(lèi):

NetworkTransporter,負(fù)責(zé)底層網(wǎng)絡(luò)通信,根據(jù)請(qǐng)求獲取數(shù)據(jù):

HtmlDownloader,通過(guò)URL獲取網(wǎng)頁(yè):

Document,表示網(wǎng)頁(yè)文檔,后續(xù)的網(wǎng)頁(yè)內(nèi)容抽取、分詞、索引都是以此為處理對(duì)象:

如何重構(gòu)?

這段代碼雖然“能用”,但不夠“好用”。

NetworkTransporter,作為一個(gè)底層網(wǎng)絡(luò)通信類(lèi),應(yīng)該盡可能通用,而不是只能下載HTML。所以,不應(yīng)該直接依賴(lài)太具體的發(fā)送對(duì)象HtmlRequest,其設(shè)計(jì)違背迪米特法則,依賴(lài)了不該有直接依賴(lài)關(guān)系的HtmlRequest類(lèi)。

假如你現(xiàn)在要去買(mǎi)東西,你肯定不會(huì)直接把錢(qián)包給收銀員,讓收銀員自己從里面拿錢(qián),而是你從錢(qián)包里把錢(qián)拿出來(lái)交給收銀員。HtmlRequest對(duì)象相當(dāng)于錢(qián)包,HtmlRequest里的address和content對(duì)象就相當(dāng)于錢(qián)。

應(yīng)將address和content交給NetworkTransporter,而非直接把HtmlRequest交給NetworkTransporter:

Document的問(wèn)題:

  • 構(gòu)造器中的downloader.downloadHtml()邏輯復(fù)雜,耗時(shí)長(zhǎng),不應(yīng)放到構(gòu)造器,影響代碼可測(cè)試性
  • HtmlDownloader對(duì)象在構(gòu)造器通過(guò)new來(lái)創(chuàng)建,違反面向接口編程,也影響代碼可測(cè)試性
  • 業(yè)務(wù)上說(shuō),Document網(wǎng)頁(yè)文檔沒(méi)必要依賴(lài)HtmlDownloader類(lèi),違背迪米特法則

問(wèn)題雖多,但修改簡(jiǎn)單:

3.2 有依賴(lài)關(guān)系的類(lèi)之間,盡量只依賴(lài)必要的接口。

Serialization類(lèi)負(fù)責(zé)對(duì)象的序列化和反序列化:

單看類(lèi)的設(shè)計(jì),沒(méi)問(wèn)題。但若放到特定應(yīng)用場(chǎng)景,假設(shè)項(xiàng)目中的有些類(lèi)只用到序列化操作,而另一些類(lèi)只用到反序列化。那么,基于 有依賴(lài)關(guān)系的類(lèi)之間,盡量只依賴(lài)必要的接口:

  • 只用到序列化操作的那部分類(lèi)不應(yīng)依賴(lài)反序列化接口
  • 只用到反序列化操作的那部分類(lèi)不應(yīng)依賴(lài)序列化接口

據(jù)此,應(yīng)將Serialization類(lèi)

方案一:拆分為兩個(gè)更小粒度的類(lèi)

  • 只負(fù)責(zé)序列化(Serializer類(lèi))
  • 只負(fù)責(zé)反序列化(Deserializer類(lèi))

盡管拆分后的代碼更能滿(mǎn)足迪米特法則,但卻違背高內(nèi)聚。高內(nèi)聚要求相近功能放到同一類(lèi)中,方便功能修改時(shí),修改的地方不太散亂。

針對(duì)本案例,若業(yè)務(wù)要求修改序列化實(shí)現(xiàn)方式,從JSON換成XML,則反序列化實(shí)現(xiàn)邏輯也要一起改。未拆分前,只需修改一個(gè)類(lèi),拆分后,卻要修改兩個(gè)類(lèi)!

既不想違背高內(nèi)聚,也不想違背迪米特法則,怎么辦?

方案二:引入兩個(gè)接口

盡管還是要往Demo1的構(gòu)造器傳入包含序列化和反序列化的Serialization實(shí)現(xiàn)類(lèi),但依賴(lài)的Serializable接口只包含序列化操作,Demo1無(wú)法使用Serialization類(lèi)中的反序列化接口,對(duì)反序列化操作無(wú)感知,符合迪米特法則的“依賴(lài)有限接口”。

也體現(xiàn)了“面向接口編程”,結(jié)合迪米特法則,可總結(jié)出:“基于最小接口,而非最大實(shí)現(xiàn)來(lái)編程”。

多想一點(diǎn)點(diǎn)

本案例的重構(gòu)方案,整個(gè)類(lèi)只包含序列化、反序列化倆操作,只用到序列化操作的使用者,即便能夠感知到僅有的一個(gè)反序列化方法,問(wèn)題也不大。為滿(mǎn)足迪米特法則,將一個(gè)簡(jiǎn)單的類(lèi),拆出兩個(gè)接口,是過(guò)度設(shè)計(jì)嗎?設(shè)計(jì)原則本身無(wú)對(duì)錯(cuò),只有能否用對(duì)之說(shuō)。不要為了用設(shè)計(jì)原則而用,應(yīng)該具體問(wèn)題具體分析。

Serialization類(lèi)只包含兩個(gè)操作,確實(shí)沒(méi)啥必要拆成倆接口。但若對(duì)Serialization類(lèi)添加更多功能,實(shí)現(xiàn)更多更好用的序列化、反序列化方法,重新考慮該問(wèn)題:

這種場(chǎng)景下,方案二設(shè)計(jì)更好。因?yàn)楸景咐膽?yīng)用場(chǎng)景,大部分代碼只用到序列化功能,這些用戶(hù)無(wú)需了解反序列化,而修改后的Serialization類(lèi),反序列化的“知識(shí)”,從一個(gè)方法變成三個(gè)。一旦任一反序列化操作有代碼改動(dòng),都需要檢查、測(cè)試所有依賴(lài)Serialization類(lèi)的代碼是否還能正常工作。

為減少耦合和降低測(cè)試的工作量,應(yīng)按迪米特法則,隔離反序列化和序列化的功能。

4.總結(jié)

4.1 高內(nèi)聚、低耦合

能有效提高代碼的可讀性和可維護(hù)性,縮小功能改動(dòng)導(dǎo)致的代碼改動(dòng)范圍:

  • 高內(nèi)聚,指導(dǎo)類(lèi)本身的設(shè)計(jì)

就是指相近的功能應(yīng)該放到同一個(gè)類(lèi)中,不相近的功能不要放到同一類(lèi)中。相近的功能往往會(huì)被同時(shí)修改,放到同一個(gè)類(lèi)中,修改會(huì)比較集中

  • 低耦合,指導(dǎo)類(lèi)與類(lèi)之間依賴(lài)關(guān)系的設(shè)計(jì)

在代碼中,類(lèi)與類(lèi)之間的依賴(lài)關(guān)系簡(jiǎn)單清晰。即使兩個(gè)類(lèi)有依賴(lài)關(guān)系,一個(gè)類(lèi)的代碼改動(dòng)也不會(huì)或者很少導(dǎo)致依賴(lài)類(lèi)的代碼改動(dòng)。

4.2 迪米特法則

不該有直接依賴(lài)關(guān)系的類(lèi)之間,不要有依賴(lài);有依賴(lài)關(guān)系的類(lèi)之間,盡量只依賴(lài)必要的接口。迪米特法則希望減少類(lèi)之間的耦合,讓類(lèi)越獨(dú)立越好。每個(gè)類(lèi)都應(yīng)該少了解系統(tǒng)的其他部分。一旦發(fā)生變化,需要了解這一變化的類(lèi)就會(huì)比較少。

參考:

[1]. 《重構(gòu)》

[2]. 《代碼設(shè)計(jì)之丑》

責(zé)任編輯:武曉燕 來(lái)源: JavaEdge
相關(guān)推薦

2012-03-12 16:10:26

Java設(shè)計(jì)模式

2024-11-14 09:42:32

2020-09-08 06:32:57

項(xiàng)目低耦合高內(nèi)聚

2023-09-05 15:00:04

微服務(wù)架構(gòu)

2021-09-13 05:01:45

軟件架構(gòu)3Rs

2022-09-02 15:35:37

Android實(shí)踐

2023-08-05 13:31:20

工廠方法模式對(duì)象

2021-09-13 10:30:42

C++代碼設(shè)計(jì)模式

2023-10-17 09:19:34

開(kāi)發(fā)Java

2022-12-12 09:42:04

PHPGo框架

2023-09-11 09:19:01

DDDJPA性能

2012-06-07 10:11:01

面向?qū)ο?/a>設(shè)計(jì)原則Java

2023-11-01 07:41:39

六邊形架構(gòu)適配器架構(gòu)

2021-09-06 11:34:47

架構(gòu)微服務(wù)Hystrix

2012-02-20 09:49:42

ibmdw

2010-01-20 09:14:49

C語(yǔ)言模塊化

2025-06-10 02:00:15

GRASP高內(nèi)聚代碼

2016-03-25 09:57:09

統(tǒng)一監(jiān)控報(bào)警平臺(tái)運(yùn)維

2022-11-11 07:58:05

業(yè)務(wù)中臺(tái)架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美日韩亚洲国产综合 | 久热久热 | 欧美日韩综合一区 | 久久久一二三 | 欧美日韩在线播放 | 欧美日韩精品免费观看 | 国产精品不卡视频 | 91www在线观看 | 精品久久久久久亚洲综合网站 | 香蕉91| 国产欧美一区二区三区久久手机版 | 国产精品久久久久久久久久妞妞 | 国产一区二区影院 | 91精品国产乱码久久久久久久 | av在线一区二区三区 | 中文字幕av网址 | 国产视频一视频二 | 亚洲精品久久久一区二区三区 | 欧美日韩精品一区二区天天拍 | 亚洲人人舔人人 | 久久国产麻豆 | 国产在线精品一区二区 | 精品在线免费观看视频 | 91原创视频在线观看 | 国产精品成人在线播放 | 国产精品日本一区二区不卡视频 | 欧美成人免费在线视频 | 成人免费视频网站在线看 | 午夜久久久 | 一区二区免费在线观看 | 夜操| 青青草精品视频 | 日批日韩在线观看 | 成人网av | 亚洲在线免费观看 | 国产 日韩 欧美 在线 | 国产视频一区二区 | 一级毛片网| 午夜电影网| 国产精品无码久久久久 | 一区二区三区国产精品 |