第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

工廠(chǎng)模式

工廠(chǎng)模式是平時(shí)開(kāi)發(fā)過(guò)程中最常見(jiàn)的設(shè)計(jì)模式。工廠(chǎng)模式解決類(lèi)的實(shí)例化問(wèn)題,它屬于創(chuàng)建型模式。工廠(chǎng)模式也經(jīng)常會(huì)和其他設(shè)計(jì)模式組合使用。

試想你去麥當(dāng)勞買(mǎi)一個(gè)漢堡。你只需要告訴收銀員要一個(gè)xx漢堡。過(guò)一會(huì)就會(huì)有一個(gè)此類(lèi)型的漢堡被制作出來(lái)。而你完全不需要知道這個(gè)漢堡是怎么被制作出來(lái)的。這個(gè)例子中你就是客戶(hù)端代碼,麥當(dāng)勞就是工廠(chǎng),負(fù)責(zé)生產(chǎn)漢堡。漢堡是接口,而具體的某一種漢堡,比如說(shuō)香辣雞腿堡,就是實(shí)現(xiàn)了漢堡接口的類(lèi)。

我們繼續(xù)通過(guò)另外一個(gè)例子,深入理解工廠(chǎng)模式?,F(xiàn)在我們給某款音樂(lè)軟件開(kāi)發(fā)一個(gè)推薦功能。需求是能夠根據(jù)用戶(hù)選擇的音樂(lè)風(fēng)格,推薦不同風(fēng)格的歌曲清單。那么你打算怎么實(shí)現(xiàn)呢?

1. 音樂(lè)推薦器1.0版本

如果之前沒(méi)有學(xué)習(xí)過(guò)設(shè)計(jì)模式,很可能你的實(shí)現(xiàn)會(huì)是這樣。編寫(xiě) RecommendMusicService 類(lèi),里面有一個(gè) Recommend方法。根據(jù)輸入的風(fēng)格不同,執(zhí)行不同的推薦邏輯。代碼如下:

public class RecommendMusicService {
    public List<String> recommend(String style) {
        List<String> recommendMusicList = new ArrayList<>();

        if ("metal".equals(style)) {
            recommendMusicList.add("Don't cry");
        } else if ("country".equals(style)) {
            recommendMusicList.add("Hotel california");
        } else if ("grunge".equals(style)) {
            recommendMusicList.add("About a girl");
        }else {
            recommendMusicList.add("My heart will go on");
        }

        return recommendMusicList;
    }
}

是不是覺(jué)得 recommed 方法太長(zhǎng)了? OK,我們重構(gòu)下,把每種音樂(lè)風(fēng)格的推薦邏輯封裝到相應(yīng)的方法中。這樣推薦方法就可以復(fù)用了。

public class RecommendMusicService {
    public List<String> recommend(String style) {
        List<String> recommendMusicList = new ArrayList<>();

        if ("metal".equals(style)) {
            recommendMetal(recommendMusicList);
        } else if ("country".equals(style)) {
            recommendCountry(recommendMusicList);
        } else if ("grunge".equals(style)) {
            recommendGrunge(recommendMusicList);
        }else {
            recommendPop(recommendMusicList);
        }

        return recommendMusicList;
    }

    private void recommendPop(List<String> recommendMusicList) {
        recommendMusicList.add("My heart will go on");
        recommendMusicList.add("Beat it");
    }

    private void recommendGrunge(List<String> recommendMusicList) {
        recommendMusicList.add("About a girl");
        recommendMusicList.add("Smells like teen spirit");
    }

    private void recommendCountry(List<String> recommendMusicList) {
        recommendMusicList.add("Hotel california");
        recommendMusicList.add("Take Me Home Country Roads");
    }

    private void recommendMetal(List<String> recommendMusicList) {
        recommendMusicList.add("Don't cry");
        recommendMusicList.add("Fade to black");
    }
}

這樣是不是很完美了!recommend 方法精簡(jiǎn)了很多,而且每種不同的推薦邏輯都被封裝到相應(yīng)的方法中了。那么,如果再加一種風(fēng)格推薦怎么辦?這有什么難,recommed 方法中加分支就好啦。然后在 RecommendMusicService 中增加一個(gè)對(duì)應(yīng)的推薦方法。
等等,是不是哪里不太對(duì)?回想一下設(shè)計(jì)模式6大原則的開(kāi)閉原則----對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。面對(duì)新風(fēng)格推薦的需求,我們一直都在修改 RecommendMusicService 這個(gè)類(lèi)。以后每次有新風(fēng)格推薦要添加,都會(huì)導(dǎo)致修改 RecommendMusicService 。顯然這是個(gè)壞味道。

那么如何做到實(shí)現(xiàn)新的風(fēng)格推薦需求時(shí),滿(mǎn)足開(kāi)閉原則呢?

2. 音樂(lè)推薦器2.0版本

添加新需求時(shí),如何做到不修改,去擴(kuò)展?是不是想到了單一職責(zé)?是的,類(lèi)的職責(zé)越單一,那么它就越穩(wěn)定。RecommendMusicService 類(lèi)的職責(zé)太多了,負(fù)責(zé)n種風(fēng)格的推薦。OK,那么我們第一件事就是要減少 RecommendMusicService 類(lèi)的職責(zé),把每種不同風(fēng)格的推薦提取到不同的類(lèi)當(dāng)中。
比如MetalMusicRecommendServicePopMusicRecommendService、CountryMusicRecommendService。這些類(lèi)都可以通過(guò) recommed 方法生成推薦的歌曲清單。而 RecommendMusicService 類(lèi)只是通過(guò)調(diào)用不同 MusicRecommendService 的 recommed 方法來(lái)實(shí)現(xiàn)推薦。代碼如下:

MetalMusicRecommendService 類(lèi):

public class MetalMusicRecommendService {
    public List<String> recommend(){
        List<String> recommendMusicList = new ArrayList<>();

        recommendMusicList.add("Don't cry");
        recommendMusicList.add("Fade to black");

        return recommendMusicList;
    }
}

同類(lèi)型的還有 GrungeMusicRecommendService、PopMusicRecommendServiceCountryMusicRecommendService 類(lèi)

現(xiàn)在我們來(lái)改造 MusicRecommendService 類(lèi):

public class RecommendMusicService {

    private MetalMusicRecommendService metalMusicRecommendService = new MetalMusicRecommendService();
    private GrungeMusicRecommendService grungeMusicRecommendService = new GrungeMusicRecommendService();
    private CountryMusicRecommendService countryMusicRecommendService = new CountryMusicRecommendService();
    private PopMusicRecommendService popMusicRecommendService = new PopMusicRecommendService();

    public List<String> recommend(String style) {
        List<String> recommendMusicList = new ArrayList<>();

        if ("metal".equals(style)) {
            metalMusicRecommendService.recommend();
        } else if ("country".equals(style)) {
            countryMusicRecommendService.recommend();
        } else if ("grunge".equals(style)) {
            grungeMusicRecommendService.recommend();
        }else {
            popMusicRecommendService.recommend();
        }

        return recommendMusicList;
    }

}

改造后,如果有了新音樂(lè)風(fēng)格推薦的需求,只需要增加相應(yīng)的 xxxMusicRecommendService 類(lèi)。然后在 RecommendMusicService 中增加相應(yīng)分支即可。這樣就做到了開(kāi)閉原則。那么還有什么違背設(shè)計(jì)原則的地方嗎?RecommendMusicService 是不是依賴(lài)的 xxMusicRecommendService 類(lèi)太多了?

沒(méi)錯(cuò),而且這么多類(lèi),實(shí)際上都是做推薦的事情,且都是通過(guò) recommend 方法提供推薦結(jié)果。這完全可以抽象出接口,比如 MusicRecommendInterface。那么 RecommendMusicService 依賴(lài) MusicRecommendInterface 就可以了。這解決了依賴(lài)反轉(zhuǎn)問(wèn)題----應(yīng)該依賴(lài)接口,而不是依賴(lài)具體實(shí)現(xiàn)。

我們又復(fù)習(xí)了單一職責(zé)和依賴(lài)反轉(zhuǎn)原則。不愧是指導(dǎo)設(shè)計(jì)模式的原則,真的是無(wú)處不在。依賴(lài) MusicRecommendInterface 沒(méi)問(wèn)題,但是不同的音樂(lè)風(fēng)格,怎么能實(shí)例化 MusicRecommendInterface 的某個(gè)具體實(shí)現(xiàn)呢?工廠(chǎng)模式于是就應(yīng)運(yùn)而生了!

3. 音樂(lè)推薦器3.0版本

我們回顧一下文章開(kāi)頭說(shuō)到,工廠(chǎng)模式解決的是類(lèi)的實(shí)例化。無(wú)論你需要哪種風(fēng)格的 MusicRecommendService,只需要告訴工廠(chǎng),工廠(chǎng)會(huì)給你實(shí)例化好你需要的具體實(shí)現(xiàn)。而工廠(chǎng)能做到這些是基于繼承和多態(tài)。
RecommendMusicService 只需要依賴(lài) MusicRecommendInterface,具體需要哪個(gè)MusicRecommendService 的實(shí)現(xiàn),只需要告訴 RecommendServiceFactory 即可。MusicRecommendService 拿到具體的實(shí)現(xiàn)后調(diào)用它的 recommand 方法,就可以得到相應(yīng)風(fēng)格的推薦歌曲清單。

首先我們需要定義所有 MusicRecommendService 要實(shí)現(xiàn)的接口,很簡(jiǎn)單,只有一個(gè) recommend 方法:

public interface MusicRecommendInterface {
    List<String> recommend();
}

我們2.0版本中的 xxxMusicRecommendService 都需要實(shí)現(xiàn)此接口,例如:

public class GrungeMusicRecommendService implements MusicRecommendInterface {
    public List<String> recommend() {
        List<String> recommendMusicList = new ArrayList<>();

        recommendMusicList.add("About a girl");
        recommendMusicList.add("Smells like teen spirit");

        return recommendMusicList;
    }
}

不同音樂(lè)風(fēng)格的推薦邏輯在各自實(shí)現(xiàn)的 recommend() 方法中。
下面就是工廠(chǎng)模式中的工廠(chǎng)代碼了,其實(shí)很簡(jiǎn)單,只是根據(jù)不同的參數(shù)實(shí)例化不同的實(shí)現(xiàn)并返回。

public class MusicRecommendServiceFactory {
    MusicRecommendInterface createMusicRecommend(String style) {
        if ("metal".equals(style)) {
            return new MetalMusicRecommendService();
        } else if ("country".equals(style)) {
            return new CountryMusicRecommendService();
        } else if ("grunge".equals(style)) {
            return new GrungeMusicRecommendService();
        } else {
            return new PopMusicRecommendService();
        }
    }
}

我們?cè)賮?lái)看看 RecommendMusicService 的代碼:

public class RecommendMusicService {

    private MusicRecommendServiceFactory recommendMusicServiceFactory = new MusicRecommendServiceFactory();

    public List<String> recommend(String style) {

        MusicRecommendInterface musicRecommend = recommendMusicServiceFactory.createMusicRecommend(style);

        return musicRecommend.recommend();
    }
}

是不是簡(jiǎn)單多了,已經(jīng)不再依賴(lài)那么多的 MusicRecommendInterface 的實(shí)現(xiàn)了。它要做的事情僅僅是通過(guò)工廠(chǎng)得到想要的 RecommendMusicService 實(shí)現(xiàn),然后調(diào)用它的 recommend() 方法,就可以得到你想要的推薦結(jié)果。
類(lèi)圖如下:
圖片描述
以上三種實(shí)現(xiàn)方式總結(jié)如下:
圖片描述

4. 小結(jié)

本節(jié)我們通過(guò)音樂(lè)推薦器的例子,實(shí)踐了如何找到程序中違反設(shè)計(jì)原則的地方,并通過(guò)工廠(chǎng)模式來(lái)解決這些問(wèn)題。使用設(shè)計(jì)模式可以讓程序更符合程序設(shè)計(jì)原則,從而寫(xiě)出更為健壯的代碼。我們應(yīng)牢記工廠(chǎng)模式解決的是類(lèi)的實(shí)例化問(wèn)題。這個(gè)例子很簡(jiǎn)單,不過(guò)涉及到的知識(shí)點(diǎn)卻很多。有封裝、多態(tài)、單一職責(zé)和依賴(lài)反轉(zhuǎn)等??梢?jiàn)要想把程序設(shè)計(jì)好,必須熟練掌握這些基本概念和原則。