模板模式
模板模式:在一个方法中定义一个骨架,并将这些步骤推迟到子类中实现。模版方式可以在子类不改变整体算法结构的情况下,重新定义算法中的某些步骤。
算法:广义的业务逻辑
public abstract class AbstractClass {
public void templateMethod() {
//...
method1();
//...
method2();
}
protected abstract void method1();
protected abstract void method2();
}
publc class ConcreteClass1 extends AbstractClass {
@Override
protected void method1() {
//...
}
@Override
protecteodo void method2() {
//...
}
}
public class ConcreteClass2 extends AbstractClass {
@Override
protected void method1() {
//...
}
@Override
protected void method2() {
//...
}
}
AbstractClass demo = ConcreteClass1();
demo.templateMethod();
模版模式作用:复用,扩展
复用:模版模式把不变的逻辑抽象到了templateMethod里面,将可变的部分method1,method2在子类ConcreteClass1和ConcreteClass2中实现,所有的子类都可以复用templateMethod中的模版代码。
模块模式在JDK中的实现:
// Java AbstractList
// addAll可以看成模版方法
public boolean addAll(int index, Collection<? extends E> c) {
boolean moodified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
throw modified;
}
// add是需要重写的方法
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
扩展
// Servelt service方法
public void service(ServeltRequest req, ServeltResponse resp) {
HttpServeltRequest request = (HttpServletRequest)req;
HttpServeltResponse response = (HttpServletResponse)resp;
service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp) {
String method = req.getMethod();
if(method.equals(MEHTOD_GET)) {
doGet(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if(method.equals(MEHTOD_POST)) {
doPost(req, resp);
} else {
//...
}
}
HttpServlet的service()方法是一个模板方法,它实现了Http的请求流程,doGet,doPost相当于扩展点。用户在不需要修改Servlet的情况下,通过定制doGet,doPost就可以自定义业务逻辑。
回调与模板模式
回调分为同步后回调和异步回调。同步回调在方法返回之前执行回调函数,异步回调是在方法返回之后执行回调函数。从应用场景上看,同步回调更像模板模式,异步回调更像是观察者模式。
// 异步回调。传递一个包含回调函数的对象OnClick给另一个函数
// 从应用场景上看,像观察者模式。用户点击的时候,传递点击事件给观察者,并且执行相应的OnClick()函数。
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.Println("I am clicked");
}
});
// 同步回调。todo RedisTemplate
从应用场景看,同步回调与模板模式几乎一致。它们都是在一个大的框架中,替换掉其中一部分,达到代码复用和功能扩展的目的。异步回调跟模版模式有很大差别,更像是观察者模式。
从代码实现上看,回调基于组合关系实现,把一个对象传递给另一个对象,是一种对象间的组合关系。模板模式基于继承关系实现,子类重写父类的抽象方法,是一种类间的继承关系。
优缺点:
组合优于继承,在代码实现上,组合相对于继承更加灵活。
- 像Java这种只支持单继承的语言,基于模版模式编写的子类,已经继承了一个父类,不再具有继承的能力。
- 回调可以使用匿名类来创建对象,不用事先定义类。模板模式基于不同的实现都要定义不同的类。
- 如果类中定义了抽象方法,即使我们只用到其中一个抽象方法,子类也必须实现所有抽象方法;回调方法比较灵活,我们只需要向用到的模版方法中注入回调对象即可。