走向面向?qū)ο蟮牧笤瓌t--迪米特原則

面向?qū)ο缶幊痰牧笤瓌t


更好的可拓展性--迪米特原則
迪米特原則的英文全稱(chēng)是Law of Demeter抵乓,縮寫(xiě)是LOD扭吁,也稱(chēng)為最少知識(shí)原則萨驶。
定義是:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解寄悯。
直白的說(shuō),就是讓對(duì)象只與最直接的朋友進(jìn)行聯(lián)系叠殷。那么什么是最直接朋友呢雹洗?每個(gè)對(duì)象都必然會(huì)與其他類(lèi)有耦合關(guān)系筛璧,兩個(gè)對(duì)象之間互相耦合就為朋友關(guān)系,這種關(guān)系類(lèi)型有很多骡男,比如組合淆游,聚合,依賴(lài)隔盛。
下面犹菱,我們就通過(guò)舉例來(lái)說(shuō)明迪米特原則

相信在外務(wù)工的朋友吮炕,都有租房的經(jīng)歷腊脱,一般情況下大家都會(huì)通過(guò)中介找房。我們通過(guò)租房進(jìn)行舉例龙亲,我們?cè)O(shè)定條件為:我只要求房子的租金和面積陕凹,中介負(fù)責(zé)將合適的房子介紹給我。以下是代碼實(shí)例鳄炉。

// 房子
public class House {
    public float area;
    public float price;

    public House(float area, float price) {
        this.area = area;
        this.price = price;
    }

    @Override
    public String toString() {
        return "House{" +
                "area=" + area +
                ", price=" + price +
                '}';
    }
}
// 中介
public class Agency {
    List<House> mHouses = new ArrayList<>();

    public Agency() {
        for (int i = 0; i < 5; i++) {
            mHouses.add(new House(100 + i, (100 + i) * 200));
        }
    }

    public List<House> getHouses() {
        return mHouses;
    }
}
//租戶
public class Tenant {
    public float houseArea;
    public float housePrice;
    public static final float diffPrice = 200.001f;
    public static final float diffArea = 0.00001f;

    public void rentHouse(Agency agency) {
        List<House> mHouses = agency.getHouses();
        for (House house : mHouses) {
            if (isRightHouse(house)) {
                System.out.println("找到合適的房子了杜耙!\n" + house.toString());
                break;
            }

        }
    }

    private boolean isRightHouse(House house) {
        return Math.abs(house.price - housePrice) < diffPrice
                && Math.abs(house.area - houseArea) < diffArea;
    }
}

從上面的代碼我們可以看到,我們的租戶類(lèi)(Tenant)不僅依賴(lài)了中介類(lèi)(Agency)拂盯,還要頻繁地與我們的房子類(lèi)(House)打交道泥技。我們的需求是:我只要求房子的租金和面積,中介負(fù)責(zé)將合適的房子介紹給我。但是現(xiàn)在是我們拿到了一大堆房子數(shù)據(jù)然后自己進(jìn)行分析和計(jì)算珊豹,這樣一來(lái)簸呈,中介的功能就被弱化了,并且導(dǎo)致我們的租戶類(lèi)(Tenant)和房子類(lèi)(House)的耦合過(guò)高店茶,因?yàn)樽鳛樽鈶舳酝杀悖覀儽仨氈婪孔?House)的細(xì)節(jié)。而此時(shí)租戶類(lèi)(Tenant)又和中介類(lèi)(Agency)保持聯(lián)系贩幻。這個(gè)時(shí)候我們就有必要進(jìn)行一定的代碼調(diào)整轿腺,去區(qū)分清楚,究竟誰(shuí)是誰(shuí)的直接朋友丛楚,讓我們的代碼清晰起來(lái)族壳。
我們通過(guò)需求進(jìn)行分析,可以得出以下幾點(diǎn):

  • 租戶只負(fù)責(zé)租房趣些,提出房子的大小要求和租金要求仿荆,其他的要交給中介來(lái)做。
  • 租戶不參與房子的分析比對(duì)坏平。
  • 中介負(fù)責(zé)與客戶進(jìn)行交流拢操,并且為客戶進(jìn)行房子的比對(duì)和篩選。

如此一來(lái)舶替,我們可以根據(jù)需求對(duì)代碼進(jìn)行如下調(diào)整:

public class Agency {
    List<House> mHouses = new ArrayList<>();

    public Agency() {
        for (int i = 0; i < 5; i++) {
            mHouses.add(new House(100 + i, (100 + i) * 200));
        }
    }

    public House rentHouse(float area, float price) {
        for (House house : mHouses) {
            if (isRightHouse(area, price, house)) {
                System.out.println("找到合適的房子了令境!\n" + house.toString());
                return house;
            }
        }
        return null;
    }

    private boolean isRightHouse(float area, float price, House house) {
        return Math.abs(house.price - price) < Tenant.diffPrice
                && Math.abs(house.area - area) < Tenant.diffArea;
    }
}

public class Tenant {
    public float houseArea;
    public float housePrice;
    public static final float diffPrice = 200.001f;
    public static final float diffArea = 0.00001f;

    public void rentHouse(Agency agency) {
        System.out.println("找到合適的房子了:" + agency.rentHouse(houseArea, housePrice));
    }
}

此處我們經(jīng)過(guò)一些簡(jiǎn)單的調(diào)整,將對(duì)房子是否符合要求的判斷放到了中介里顾瞪,這其實(shí)本就應(yīng)該是中介的職責(zé)舔庶,根據(jù)用戶設(shè)定的條件去尋找房子,找到了就告訴用戶就可以了陈醒。而用戶也不需要知道有多少房源栖茉,每個(gè)房子是什么樣,他只需要詢(xún)問(wèn)中介孵延,中介告知結(jié)果即可吕漂。
從上述代碼我們可以看到,我們通過(guò)一次簡(jiǎn)單的代碼修改后尘应,代碼的耦合性已經(jīng)降低了很多惶凝,同時(shí),他們都達(dá)成了與最直接的朋友聯(lián)系的條件犬钢,將各個(gè)角色從復(fù)雜的關(guān)系中抽離出來(lái)苍鲜,使程序的耦合更低,穩(wěn)定性更好玷犹。
這里我們?cè)俅位貞浺幌挛覀僆mageLoader中的代碼混滔,就拿SD卡緩存來(lái)說(shuō),ImageCache就是用戶的直接朋友,而SD卡緩存內(nèi)部卻是使用了DiskCache實(shí)現(xiàn)坯屿,這個(gè)DiskCahce就不是用戶的直接朋友了油湖,因此,其實(shí)用戶完全不需要知道有這樣的緩存存在领跛,用戶只需要和ImageCache打交道就好了乏德,我們之前的代碼我再次優(yōu)化過(guò),使用了JakeWhartonDiskLruCache吠昭,最后代碼如下:

public void put(String url, Bitmap bitmap) {
    DiskLruCache.Editor editor = null;
    //如果沒(méi)有在內(nèi)存緩存和磁盤(pán)緩存中找到對(duì)對(duì)應(yīng)的緩存喊括,從網(wǎng)絡(luò)上請(qǐng)求數(shù)據(jù)
    //寫(xiě)入緩存
    editor = mDiskLruCache.edit(url);
    try {
        if (editor != null) {
            OutputStream out = editor.newOutputStream(0);
            if (writeBitmapToDisk(value, out)) {
                //寫(xiě)入SD卡
                editor.commit();
            } else {
                editor.abort();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    CloseUtils.colse(out);
}

用戶在使用SD卡緩存的時(shí)候,根本不知道DiskLruCache的實(shí)現(xiàn)矢棚,這就很好地對(duì)用戶隱藏了具體的代碼實(shí)現(xiàn)郑什。當(dāng)你能夠自己去寫(xiě)DiskLruCache的時(shí)候,你就可以隨意替換掉此處我們引用的JakeWharton大神的DiskLruCache了蒲肋。


總結(jié)#

一不小心蘑拯,六個(gè)章節(jié)的《走向面向?qū)ο蟮牧笤瓌t》就到此結(jié)束了,在這里感謝何紅輝肉津、關(guān)愛(ài)民先生所著的《Android設(shè)計(jì)模式》一書(shū),給我了很多啟發(fā)和靈感舱沧,并且示例上提供了很多借鑒妹沙。
時(shí)間總是很快,快到你都注意不到自己的胡渣子又冒出來(lái)了熟吏,在我們開(kāi)發(fā)的過(guò)程中距糖,最難的不是開(kāi)發(fā)出用戶所需要的功能,而是在后續(xù)的升級(jí)和維護(hù)過(guò)程中牵寺,讓系統(tǒng)能夠擁抱變化悍引,不因?yàn)榘姹镜牡露茐哪K的完整性和代碼的條理性,保證代碼的低耦合帽氓,高可拓展性趣斤,高內(nèi)聚,在經(jīng)理了N個(gè)版本的迭代以后黎休,軟件系統(tǒng)依舊能夠保持穩(wěn)健浓领,靈活,清晰的架構(gòu)势腮。
當(dāng)然啦联贩,這只是一個(gè)理想的情況,代碼迭代而引發(fā)的坑捎拯,我們爬的還少嗎泪幌?為了少爬坑,為了讓自己的代碼更漂亮,系統(tǒng)更穩(wěn)定祸泪,我們必須朝著這個(gè)方向去努力吗浩,遵循面向?qū)ο蟮牧笤瓌t,就是我們走出的浴滴,第一步拓萌。
明天的將會(huì)寫(xiě)關(guān)于單例模式的一些理解和示例,感謝大家的一直支持升略,我們共同進(jìn)步微王!
謝謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末品嚣,一起剝皮案震驚了整個(gè)濱河市炕倘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翰撑,老刑警劉巖罩旋,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異眶诈,居然都是意外死亡涨醋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)逝撬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)浴骂,“玉大人,你說(shuō)我怎么就攤上這事宪潮∷菥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵狡相,是天一觀的道長(zhǎng)梯轻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)尽棕,這世上最難降的妖魔是什么喳挑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮滔悉,結(jié)果婚禮上蟀悦,老公的妹妹穿的比我還像新娘。我一直安慰自己氧敢,他們只是感情好日戈,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著孙乖,像睡著了一般浙炼。 火紅的嫁衣襯著肌膚如雪份氧。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,713評(píng)論 1 312
  • 那天弯屈,我揣著相機(jī)與錄音蜗帜,去河邊找鬼。 笑死资厉,一個(gè)胖子當(dāng)著我的面吹牛厅缺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宴偿,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼湘捎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窄刘?” 一聲冷哼從身側(cè)響起窥妇,我...
    開(kāi)封第一講書(shū)人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎娩践,沒(méi)想到半個(gè)月后活翩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翻伺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年材泄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吨岭。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拉宗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出未妹,到底是詐尸還是另有隱情簿废,我是刑警寧澤空入,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布络它,位于F島的核電站,受9級(jí)特大地震影響歪赢,放射性物質(zhì)發(fā)生泄漏化戳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一埋凯、第九天 我趴在偏房一處隱蔽的房頂上張望点楼。 院中可真熱鬧,春花似錦白对、人聲如沸掠廓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蟀瞧。三九已至沉颂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悦污,已是汗流浹背铸屉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留切端,地道東北人彻坛。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像踏枣,于是被迫代替她去往敵國(guó)和親昌屉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容