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

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

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

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

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

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

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

第1步:先定義下載抽象類AbstractImageLoader

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

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

第2步: jpg下載類

/**
 * jpg下載類
 */
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下載類

/**
 * webp下載類
 */
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è)人類 抽象類

/**
 * 人類  抽象類
 */
public abstract class AbstractPerson {

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

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

第2步: 學(xué)生類

/**
 * 學(xué)生類
 */
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步: 老師類

/**
 * 老師類
 */
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ù)。

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

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