Head First設計模式學習—模板方法、策略模式

參考資料:
1. head first 設計模式
2. http://blog.csdn.net/hguisu/article/details/7558249/


在看設計模式的時候,總覺得好多設計模式都差不多,容易弄混,因此做點記錄。

一、模板方法

模板方法模式在一個方法中定義了一個算法的步驟(骨架),而將一些步驟延遲到子類中。模板方法使得子類在不改變算法結構的情況下,重新定義算法中的某些步驟。模板方法模式的一般結構如下圖所示:
這裏寫圖片描述
注:圖片來自Head First 設計模式中文版截圖

可以看到模板方法模式一般是針對一個算法的各個步驟進行操作,算法的步驟由超類AbstractClass控制,子類ConcreteClass只是實現了父類算法的某幾個步驟,本身並不控制算法流程(這點要與下面的策略模式區分)。模板方法模式有幾個好處:

  1. 算法流程只由超類AbstractClass控制,子類無法去修改算法流程(比如算法的執行順序等,不過可以通過在父類中加入像“鉤子”的方法實際上是可以修改算法流程),但是可以修改算法中的某個步驟細節。這樣要修改算法比較容易,同時也保護了算法(畢竟只由AbstractClass一個類控制)
  2. 算法中通用的步驟可以放在超類中實現,利用繼承實現了代碼複用

舉個可能比較牽強的例子,比如我在北京,要回到江西去,有一種路線是:北京->武漢->江西,那麼這裏 北京->武漢->江西 這個路線流程就是從北京去往江西的一個算法,這個算法分成了兩個步驟:北京->武漢,武漢->江西,假設北京到武漢只有高鐵,那我只能坐高鐵了,但是從武漢到江西既有高鐵又有硬座,於是我們設計的代碼結構如下:

/**
 * 從北京到江西路線算法框架類,確定了整體框架,其中某些步驟需要子類具體實現
 * */
public abstract class AbstractFromBeijingToJiangXi {
    /**
     * 算法框架,定義成final,避免子類去修改算法框架
     * */
    public final void fromBeijingToJiangXi(){ 
        fromBeijingToWuHan();
        fromWuhanToJiangXi();
    }
    /**
     * 這個是算法步驟中變化的步驟,不同的子類有不同的實現
     * */
    public abstract void fromWuhanToJiangXi();
    /**
     * 這個是算法的通用步驟,子類不需要實現
     * */
    public final void fromBeijingToWuHan(){
        System.out.println("坐高鐵從:北京 -> 武漢");
    }
}

以下是兩個子類的實現:

/**
 * 坐高鐵
 * */
public class CRHFromBeijingToJiangXi extends AbstractFromBeijingToJiangXi{
    /**
     * 子類重寫的步驟
     * */
    @Override
    public void fromWuhanToJiangXi() {
        System.out.println("坐高鐵從:武漢 -> 江西 ");
    }

}
/**
 * 做普通硬座
 * */
public class NormalFromBeijingToJiangXi extends AbstractFromBeijingToJiangXi {

    @Override
    public void fromWuhanToJiangXi() {
        System.out.println("坐硬座從:武漢-> 江西 ");
    }

}

我們這樣使用:

public class Client {
    public static void main(String[] args) {
        //AbstractFromBeijingToJiangXi road=new CRHFromBeijingToJiangXi();
        AbstractFromBeijingToJiangXi road=new NormalFromBeijingToJiangXi();
        road.fromBeijingToJiangXi();
    }
}

二、策略模式
策略模式定義了算法族,分別封裝起來,讓它們之間可以相互替換,此模式讓算法的變化獨立於使用算法的客戶。還是以上面的例子爲例,從北京到江西,可以有多種交通方案(每種交通方案相當於一個算法)。得到如下的代碼結構:

/**
 * 算法族的公共接口
 * */
public interface IFromBeijingToJiangXi {
    /**
     * 不同的算法有不同的實現,子類完全控制算法的步驟流程
     * */
    public void fromBeijingToJiangXi();
}

子類完全自己實現算法

/**
 * 坐高鐵
 * */
public class CRHFromBeijingToJiangXi implements IFromBeijingToJiangXi{
    /**
     * 子類自己完全實現算法的流程
     * */
    @Override
    public void fromBeijingToJiangXi() {
        fromBeijingToWuHan();
        fromWuhanToJiangXi();
    }
    public void fromBeijingToWuHan(){
        System.out.println("坐高鐵從:北京-> 武漢 ");
    }
    public void fromWuhanToJiangXi(){
        System.out.println("坐高鐵從:武漢->江西 ");
    }
}
/**
 * 做普通硬座
 * */
public class NormalFromBeijingToJiangXi implements IFromBeijingToJiangXi {
    /**
     * 子類自己完全實現算法的流程
     * */
    @Override
    public void fromBeijingToJiangXi() {
        fromBeijingToWuHan();
        fromWuhanToJiangXi();
    }
    public void fromBeijingToWuHan(){
        System.out.println("坐硬座從:北京-> 武漢 ");
    }
    public void fromWuhanToJiangXi(){
        System.out.println("坐硬座從:武漢->江西 ");
    }
}

如何使用:

public class Client {
    private IFromBeijingToJiangXi fromBeijingToJiangXi;
    public Client(IFromBeijingToJiangXi fromBeijingToJiangXi){
        this.fromBeijingToJiangXi=fromBeijingToJiangXi;
    }
    public void travel(){
        fromBeijingToJiangXi.fromBeijingToJiangXi();
    }
    public static void main(String[] args) {
        //客戶端使用時需要事先知道對應的具體的算法
        IFromBeijingToJiangXi fromBeijingToJiangXi=new CRHFromBeijingToJiangXi();
        //可以換不同的算法
        //IFromBeijingToJiangXi fromBeijingToJiangXi=new NormalFromBeijingToJiangXi();
        Client client=new Client(fromBeijingToJiangXi);
        client.travel();
    }
}

三、 二者的區別
1. 二者針對的對象的粒度不同,給我感覺模板方法模式是以算法的步驟爲單位,而策略模式是以算法爲單位
2. 模板方法模式的子類只修改了算法的某些步驟,並不會去改變算法的框架流程,而策略模式的子類則自己完全定義了算法的步驟和流程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章