模板方法及观察者模式
1、本文主要内容
- 模板方法定义
- 模板方法示例
- 观察者模式
本文主要讲两个设计模式,模板方法以及观察者模式,模板方法也是个非常有意思的设计模式,它强调的是模板以及子类的微调。观察者模式,对于我们来说则是非常熟悉的,在android中设置的种类listener都是观察者模式,因此本文不详述它了。
1、模板方法定义
模板方法UML类图模板方法:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤
模板方法,它强调的是父类已经将算法的步骤确定好了,但步骤中的某些细节让子类自己实现。例如,泡茶或泡咖啡,大概都分成4个步骤 :
- 烧水
- 用水冲泡
- 将茶或咖啡倒入水杯中
- 添加附加物,如糖,柠檬等
这种情况就可以使用模板方法,因为步骤基本确定(4个步骤),只有细节不同,接下来我们来看具体的代码示例。
3、模板方法示例
饮料超类:
public abstract class Drinks {
protected void boilWater(){
System.out.println("烧水了");
}
protected abstract void brew();
protected void pourInCup() {
System.out.println("倒入杯中");
}
protected abstract void addCondiments();
protected void hook(){};
public final void prepareRecipe(){
boilWater();
brew();
pourInCup();
addCondiments();
hook();
}
}
茶:
public class Tee extends Drinks{
@Override
protected void brew() {
System.out.println("冲泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("添加一块柠檬");
}
}
咖啡:
public class Coffee extends Drinks{
@Override
protected void brew() {
System.out.println("冲泡咖啡");
}
@Override
protected void addCondiments() {
System.out.println("添加糖,牛奶");
}
@Override
protected void hook() {
System.out.println("再添加一点椰粉");
}
}
接下来看人怎么冲泡了:
public class Client {
public static void main(String[] args) {
Coffee coffee = new Coffee();
coffee.prepareRecipe();
System.out.println("----------------");
Tee tee = new Tee();
tee.prepareRecipe();
}
}
最终的结果如下:
烧水了
冲泡咖啡
倒入杯中
添加糖,牛奶
再添加一点椰粉
----------------
烧水了
冲泡茶叶
倒入杯中
添加一块柠檬
示例代码较为简单,注意,在Drinks超类中,我们定义了一个hook方法,中文名叫钩子函数,因为模板方法中已经为了我们定义好步骤了,如果我们要再加额外步骤呢?此时就可以用上hook函数了,比如在咖啡中,用户还要再加点椰粉。
hook函数,上述的做法只是其中之一,如果思维再开放一点,只要是能改变或者影响整流流程的,都算是钩子函数。比如,用户喝茶,并不需要加柠檬,我们可以重写Tee类中的 addCondiments ,根据客户需要,不要我们就不添加,这也算是钩子函数
钩子函数的意义在于,超类已经定好整个算法框架了,能够让子类有更大的灵活以及自由度。
3、观察者模式
观察者模式非常常见,一般对应的形式为一对多,也有一对一的,比如 view 的点击事件。它的UML图为:
一般subject类中提供注册以及反注册Observer的方法,当改变发生时,subject 则调用自己的成员变量 Observer,告诉改变。