談?wù)勀0宸椒ㄔO(shè)計(jì)模式的使用

在項(xiàng)目中經(jīng)常會(huì)遇到一個(gè)類(lèi)的某些方法和另一個(gè)類(lèi)的某些方法功能是相同的,只有部分方法是不同的。這個(gè)時(shí)候就可以使用模板方法來(lái)操作了。其實(shí)這種情況很常見(jiàn):比如我們項(xiàng)目里面用到的基類(lèi),BaseActivity之類(lèi)的。這種設(shè)計(jì)就是模板方法,是不是有點(diǎn)熟悉。。。下面來(lái)看看是怎么實(shí)現(xiàn)的把。

模版方法模式的結(jié)構(gòu)
  模版方法模式由一個(gè)抽象類(lèi)和一個(gè)(或一組)實(shí)現(xiàn)類(lèi)通過(guò)繼承結(jié)構(gòu)組成,抽象類(lèi)中的方法分為三種:
  抽象方法:父類(lèi)中只聲明但不加以實(shí)現(xiàn),而是定義好規(guī)范,然后由它的子類(lèi)去實(shí)現(xiàn)。
  模版方法:由抽象類(lèi)聲明并加以實(shí)現(xiàn)。一般來(lái)說(shuō),模版方法調(diào)用抽象方法來(lái)完成主要的邏輯功能,并且,模版方法大多會(huì)定義為final類(lèi)型,指明主要的邏輯功能在子類(lèi)中不能被重寫(xiě)。
  鉤子方法:由抽象類(lèi)聲明并加以實(shí)現(xiàn)。但是子類(lèi)可以去擴(kuò)展,子類(lèi)可以通過(guò)擴(kuò)展鉤子方法來(lái)影響模版方法的邏輯。
抽象類(lèi)的任務(wù)是搭建邏輯的框架,通常由經(jīng)驗(yàn)豐富的人員編寫(xiě),因?yàn)槌橄箢?lèi)的好壞直接決定了程序是否穩(wěn)定性。
  
  實(shí)現(xiàn)類(lèi)用來(lái)實(shí)現(xiàn)細(xì)節(jié)。抽象類(lèi)中的模版方法正是通過(guò)實(shí)現(xiàn)類(lèi)擴(kuò)展的方法來(lái)完成業(yè)務(wù)邏輯。只要實(shí)現(xiàn)類(lèi)中的擴(kuò)展方法通過(guò)了單元測(cè)試,在模版方法正確的前提下,整體功能一般不會(huì)出現(xiàn)大的錯(cuò)誤。

模版方法的優(yōu)點(diǎn)
(一)容易擴(kuò)展。一般來(lái)說(shuō),抽象類(lèi)中的模版方法是不易反生改變的部分,而抽象方法是容易反生變化的部分,因此通過(guò)增加實(shí)現(xiàn)類(lèi)一般可以很容易實(shí)現(xiàn)功能的擴(kuò)展,符合開(kāi)閉原則。
(二)便于維護(hù)。對(duì)于模版方法模式來(lái)說(shuō),正是由于他們的主要邏輯相同,才使用了模版方法,假如不使用模版方法,任由這些相同的代碼散亂的分布在不同的類(lèi)中,維護(hù)起來(lái)是非常不方便的。
(三)比較靈活。因?yàn)橛秀^子方法,因此,子類(lèi)的實(shí)現(xiàn)也可以影響父類(lèi)中主邏輯的運(yùn)行。但是,在靈活的同時(shí),由于子類(lèi)影響到了父類(lèi),違反了里氏替換原則,也會(huì)給程序帶來(lái)風(fēng)險(xiǎn)。這就對(duì)抽象類(lèi)的設(shè)計(jì)有了更高的要求。

模版方法的適用場(chǎng)景
  在多個(gè)子類(lèi)擁有相同的方法,并且這些方法邏輯相同時(shí),可以考慮使用模版方法模式。在程序的主框架相同,細(xì)節(jié)不同的場(chǎng)合下,也比較適合使用這種模式。

示例1:下面代碼實(shí)例說(shuō)明:

比如說(shuō)使用glide加載圖片的時(shí)候,我可以寫(xiě)一個(gè)抽象類(lèi)來(lái)管理一些共性的東西,然后之內(nèi)具體去實(shí)現(xiàn),下面我寫(xiě)一個(gè)抽象類(lèi):

第1步:先定義下載抽象類(lèi)AbstractImageLoader

/**
 * 先定義下載抽象類(lèi)AbstractImageLoader
 */
public abstract class AbstractImageLoader {
    //抽象類(lèi)定義整個(gè)流程骨架
    public final void downloadImage(String imageUrl,int width,int height){
        //先獲取最終的數(shù)據(jù)源URL
        String finalImageUrl=getUrl(imageUrl,width,height);
        //然后開(kāi)始執(zhí)行下載
    }

    //以下是不同子類(lèi)根據(jù)自身特性完成的具體步驟
    protected abstract String getUrl(String imageUrl,int width,int height);
}

第2步: jpg下載類(lèi)

/**
 * jpg下載類(lèi)
 */
public class jpgImageLoader extends AbstractImageLoader{
    @Override
    protected String getUrl(String imageUrl, int width, int height) {
        return String.format("%s?imageView2/1/w/%d/h/%d/format/webp", 
                                imageUrl, width, height);
    }
}

第3步: webp下載類(lèi)

/**
 * webp下載類(lèi)
 */
public class WebpImageLoader extends AbstractImageLoader{
    @Override
    protected String getUrl(String imageUrl, int width, int height) {
        return String.format("%s?imageView2/1/w/%d/h/%d/format/jpg", 
                        imageUrl, width, height);
    }
}

第4步: 代碼里面使用

public class MainActivity5 extends AppCompatActivity{
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main5);
        findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String imageUrl = 
                          "http://img.my.csdn.net/uploads/201309/01/
                                                    1378037235_7476.jpg";
                AbstractImageLoader loader =new  WebpImageLoader();
                loader.downloadImage(imageUrl,200,200);
            }
        });
    }
}

示例2:再來(lái)一個(gè)實(shí)例說(shuō)明一下:

第1步: 寫(xiě)一個(gè)人類(lèi) 抽象類(lèi)

/**
 * 人類(lèi)  抽象類(lèi)
 */
public abstract class AbstractPerson {

    //抽象類(lèi)定義整個(gè)流程骨架
    public void prepareGotoSchool(){
        dressUp();
        eatBreakfast();
        takeThings();
    }

    //以下是不同子類(lèi)根據(jù)自身特性完成的具體步驟 ,交給子類(lèi)實(shí)現(xiàn)
    protected abstract void dressUp();
    protected abstract void eatBreakfast();
    protected abstract void takeThings();
}

第2步: 學(xué)生類(lèi)

/**
 * 學(xué)生類(lèi)
 */
public class StudentOne extends AbstractPerson {
    @Override
    protected void dressUp() {
        Log.i("dressUp: ","穿校服");
    }

    @Override
    protected void eatBreakfast() {
        Log.i("eatBreakfast: ","吃媽媽做好的早飯");
    }

    @Override
    protected void takeThings() {
        Log.i("takeThings: ","背書(shū)包,帶上家庭作業(yè)和紅領(lǐng)巾");
    }
}

第3步: 老師類(lèi)

/**
 * 老師類(lèi)
 */
public class TeacherOne extends AbstractPerson {
    @Override
    protected void dressUp() {
        Log.i("dressUp: ", "穿工作服");
    }

    @Override
    protected void eatBreakfast() {
        Log.i("eatBreakfast: ", "做早飯,照顧孩子吃早飯");
    }

    @Override
    protected void takeThings() {
        Log.i("takeThings: ", "帶上昨晚準(zhǔn)備的考卷");
    }

}

第4步: 代碼里面使用

TeacherOne teacherOne = new TeacherOne();
teacherOne.dressUp();

通用模板

public abstract class AbstractClass{
    //基本方法
    protected abstract void doSomething();
    //基本方法
    protected abstract void doAnything();
    //模板方法
    public final void tempeteMethod(){
        this.doSomething();
        this.doAnything();
    }
}
  

public class ConcreteClass1 extends AbstractClass{
    protected void doAnything(){
        //邏輯處理
    }
    protected void doSomething(){
        //邏輯處理
    }
}

public class ConcreteClass2 extends AbstractClass{
    protected void doAnything(){
        //邏輯處理
    }
    protected void doSomething(){
        //邏輯處理
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,489評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,290評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,776評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,510評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,866評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,036評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,585評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,331評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,536評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,754評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,154評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,469評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,273評(píng)論 3 399
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,505評(píng)論 2 379

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,733評(píng)論 18 399
  • 1 場(chǎng)景問(wèn)題# 1.1 登錄控制## 幾乎所有的應(yīng)用系統(tǒng),都需要系統(tǒng)登錄控制的功能,有些系統(tǒng)甚至有多個(gè)登錄控制的功...
    七寸知架構(gòu)閱讀 1,998評(píng)論 3 53
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,961評(píng)論 1 15
  • Iterator模式 (迭代器) 一個(gè)一個(gè)遍歷 一個(gè)集合類(lèi)可以遵守 Iterator 協(xié)議,并實(shí)現(xiàn)一個(gè) Itera...
    SSBun閱讀 1,860評(píng)論 0 15
  • 記得上次排休,還是在7月10號(hào),距離今天已有一個(gè)半月之久。 這一個(gè)半月,也是夏天最熱的時(shí)候。 今年的夏天比去年較忙...
    雪花一擁抱生活_淡定人生閱讀 286評(píng)論 12 6