背景
- 设计模式是“前人”提炼的代码思想的精华?什么?这听着太高大上了,我可没用过?什么,你没用过?那不可能,作为Android从业主,你没setOnClickListener()吗?你没有抽取公共代码到基类BaseActivity/BaseFragment里面吗?你已经在使用设计模式了好不好?
定义
- 定义一个操作中的算法框架,而将一些步骤延迟到子类中实现,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
要点
- 抽象模板:定义模板结构,让子类具体实现;
- 具体模板:具体实现抽象类的抽象方法。
场景
- 将一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而将一些可以改变的细节由其子类来实现;
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复;
- 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反响控制(钩子)。
优缺点
- 优点:
- 1.1代码复用,相同部分代码都放在抽象的父类中;
- 1.2.父类控制方法,子类负责实现,良好的扩展性;
- 1.3.反向控制,通过父类调用子类的操作,通过子类的扩展添加新的行为。
- 缺点:
- 代码的阅读难度会增加,我们习惯性认为抽象类声明的都是最抽象的、最一般的事物属性和方法,实现类完成 * 具体事物属性和方法;而在模板方法模式中,抽象类中定义了部分抽象方法,而子类实现父类方法后执行的结果影响了父类, * 子类对父类产生了影响。
- 代码的阅读难度会增加,我们习惯性认为抽象类声明的都是最抽象的、最一般的事物属性和方法,实现类完成 * 具体事物属性和方法;而在模板方法模式中,抽象类中定义了部分抽象方法,而子类实现父类方法后执行的结果影响了父类, * 子类对父类产生了影响。
代码演示
- 抽象父类
/*
* 以煮面为例子
*/
public abstract class CookNoodles {
//聲明稱final防止被重寫覆蓋
public final void cookNoodles() {
heatUpWater();
putNoodles2Water();
if (isNeedSeasoning()) {
putSeasoning();
}
}
/**
* 燒水是煮面必须的步骤,这是唯一的,可以确定的,就可以在父类中进行实现,没有必要交给子类
*/
private void heatUpWater() {
System.out.println("咕嘟嘟,水烧好了");
};
/**
* 把面放入沸水中,有的喜欢红烧牛肉面,有的喜欢老坛酸菜,有的喜欢挂面,既然这么不确定交给子类来实现吧
*/
protected abstract void putNoodles2Water();
/**
* 默认放調料,不想要你可以复写isNeedSeasoning方法提出来
*/
protected void putSeasoning() {
System.out.println("加一波南德调料,巴适得很");
};
/**有的口味重,有的口味淡,调料不是必须放的,提供一个hook,自己觉得放不放
* 鉤子方法
*
* 判断是否需要放调料。默认true要放
* @return
*/
protected boolean isNeedSeasoning() {
return true;
}
}复制代码
2. 子类1:
/**
* 吃挂面,放调料
* @author Administrator
*
*/
public class GuaMian extends CookNoodles {
@Override
protected void putNoodles2Water() {
System.out.println("挂面来一斤");
}
}
复制代码
3. 子类2:
/**
* 来碗红烧牛肉面,默认要调料
* @author Administrator
*
*/
public class HongShao extends CookNoodles{
@Override
protected void putNoodles2Water() {
System.out.println("放入红烧牛肉面");
}
}
复制代码
4. 子类3:
/**
* 来一碗老坛酸菜面,提出不要放调料,就喜欢酸菜的本味
* @author Administrator
*
*/
public class SuanCai extends CookNoodles{
@Override
protected void putNoodles2Water() {
System.out.println("放入老坛酸菜");
}
/**
* 不放调料,返回false
*/
@Override
protected boolean isNeedSeasoning() {
return false;
}
}
复制代码
5. 测试类:
public class TestDemo {
public static void main(String[] args) {
new HongShao().cookNoodles();
System.out.println("--------------------");
new SuanCai().cookNoodles();
System.out.println("--------------------");
new GuaMian().cookNoodles();
}
}
复制代码
6. 执行结果:
咕嘟嘟,水烧好了
放入红烧牛肉面
加一波南德调料,巴适得很
--------------------
咕嘟嘟,水烧好了
放入老坛酸菜
--------------------
咕嘟嘟,水烧好了
挂面来一斤
加一波南德调料,巴适得很
复制代码