一、引言
不可否认,编代码、写程序,编的写的其实是人的思想;而设计模式更是这种思想的总结。“求同存异”是周总理的闻名外交思想之一,“求同”就是寻求相同的地方,并且来解决它;“存异”就是搁置不同的地方,搁置的意思不是不解决,而是留待后面去解决。
在设计模式中,模板方法正是体现了这种思想的典范。
模板方法,定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中。其中,这些在父类中实现了的步骤就是所谓的“同”,“求同”就是在父类中把相同的功能先实现;而那些延迟到子类中的步骤就是所谓的“异”,“存异”就是把不同在父类中遗留下来,到子类中去各个实现。
在实际的工作中,经常会碰到这样的情况:有一序列的功能相同的模块,这些模板有很多相同或相似的步骤;当然,也有一个或两个不同的步骤。
如,有在线购物功能的网站,经常要对商品进行各种各样的排名:按商品的点击率排名、按商品的购买率排名、按商品的入站时间排名、按商品的类别进行的搜索等等。这些都是一些搜索功能,功能完全相同;不同的要么是搜索的算法、要么是搜索的数据表不同。
我们知道,假如采用Struts模式的开发方法,那么我们所有的这些功能的实现都是在一个继续了Action类的public ActionForward execute ( ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response)中实现,这里需要实现的功能有:取得进行搜索所需要的各种条件,进行搜索算法、处理搜索结果。在这里,取得搜索所需的条件和处理搜索结果的算法是一样的,他们将产生相同的代码。不同的只是进行搜索的算法。很明显,相同的代码是需要我们进行重用的。
那么我们该怎么重用呢?
二、从一段代码谈起
首先需要说明的是:这段代码是一段反面的代码,或者说是一段坏的代码。每个人看了都会觉得不可思议,但这确确实实是我们工作中碰到的代码:
public class ToSpeAction extends Action {
public ArrayList sizeRangeLabel = null;
public ActionForward execute ( ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) {
……
if ("Save".equalsIgnoreCase (action)) {
StringBuffer prodUCtIDStr = new StringBuffer ( );
StringBuffer speciStr = new StringBuffer ( );
SpeciManager.getInstance ( ).saveHeadData (actionForm, request, productIDStr, speciStr, "specification");
specId = speciStr.toString ( );
ProductID = productIDStr.toString ( );
form.set ("ProductID", ProductID);
form.set ("specId", specId);
}
……
//grid
if (tab.equals ("0")) { //spec
GridDataSummary gdSmy = new GridDataSummary (specId);
gdSmy.specBaseData.setTransform (transform);
gdSmy.specBaseData.setPrevTransform (prevTransform);
gdSmy.specBaseData.setTextRangeSizeSrc ((String) form.get ("sizeRangeIDesc"));
gdSmy.specBaseData.setSortPomStr (sortPomStr);
gdSmy.specBaseData.setGradeRuleId ((String) form.get ("ddlGuleVule"));
gdSmy.specBaseData.setSizeChangeflag ((String) form.get ("sizeChangeFlag"));
gdSmy.specBaseData.setHidePOMCode ("Hide".equalsIgnoreCase (hidePOMCode) ?