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. 模板方法模式的子类只修改了算法的某些步骤,并不会去改变算法的框架流程,而策略模式的子类则自己完全定义了算法的步骤和流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zlp1992

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值