Java设计模式中的模板模式
在看MapReduce的内容时讲到Mapper和Reducer中的设计模式为模板模式。
如下是Mapper:
public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> { /** * The <code>Context</code> passed on to the {@link Mapper} implementations. */ public abstract class Context implements MapContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT> { } /** * Called once at the beginning of the task. */ protected void setup(Context context ) throws IOException, InterruptedException { // NOTHING } /** * Called once for each key/value pair in the input split. Most applications * should override this, but the default is the identity function. */ @SuppressWarnings("unchecked") protected void map(KEYIN key, VALUEIN value, Context context) throws IOException, InterruptedException { context.write((KEYOUT) key, (VALUEOUT) value); } /** * Called once at the end of the task. */ protected void cleanup(Context context ) throws IOException, InterruptedException { // NOTHING } /** * Expert users can override this method for more complete control over the * execution of the Mapper. * @param context * @throws IOException */ public void run(Context context) throws IOException, InterruptedException { setup(context); try { while (context.nextKeyValue()) { map(context.getCurrentKey(), context.getCurrentValue(), context); } } finally { cleanup(context); } }
模板模式就是通过抽象类来定义一个逻辑模板,逻辑框架、逻辑原型,然后将无法决定的部分抽象成抽象类交由子类来实现,一般这些抽象类的调用逻辑还是在抽象类中完成的。
如在上面的Mapper中,有setup,map,cleanup,run的逻辑框架,在使用MapReduce的Mapper时,只需要重写map方法即可。
模板模式中分基本方法和模板方法,上述的run可看做基本方法,需要调用其它方法实现整体逻辑,不会被修改,其它几个方法可看做模板方法。基本方法一般会用final修饰,保证其不会被子类修改,而模板方法使用protect修饰,表示需要在子类中实现。
此外,模板模式中还有一个叫钩子方法的概念,即给子类一个授权,允许子类通过重写钩子方法来颠覆基本逻辑的执行,这有时候是非常有用的,可以用来完善具体的逻辑。