模版方法模式/Template Method

本文详细解释了模版方法模式的概念、意图、适用场景、UML表示、参与者、要点、方法类型以及提供了具体的示例代码,帮助读者理解如何在实际编程中运用这一模式。

模版方法模式/Template Method

意图/适用场景:

模版方法模式其实是一种应用很广泛的模式,特别是在使用抽象类的时候。

模版方法模式中必然有一个核心的抽象类,不能是接口。声明一些抽象方法,这些方法由子类来做各不相同的实现;也可以是一些非抽象的方法,这些方法只是做为默认的实现,子类应该覆盖它们。

此外,还要定义一个或多少具体的方法,它们实现一些逻辑,调用前面提到的抽象或非抽象方法。这种方法就本模式中最重要的部分,这样的方法一般规定了调用其它抽象方法的逻辑,所以它是一个模版,这个方法就称为模版方法。

模版方法一般不被子类覆盖,否则就失去了“模版”的作用。

UML:

模版方法模式/Template <wbr>Method

参与者:

  1. 抽象模版(Abstract Template):
    • 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作。
    • 定义并实现一个模版方法,这是一个具体的方法,给出了一个逻辑骨架,以固定的顺序和条件来调用其它的抽象方法。它定义了调用逻辑,是一个模版。
  2. 具体模版(Concrete Template):
    • 以自己的方式实现父类所定义的抽象方法。

要点:

模版方法模式中的方法:

  1. 模版方法:
    • 一个模版方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个方法在抽象类中定义,并由子类不加修改地完全继承。
  2. 基本方法:

主要由子类来实现或重写,体现继承关系的方法称为基本方法。基本方法又可以分为三种:

  • 抽象方法:必须由子类来实现的方法。
  • 具体方法:具体方法仍然由抽象类实现,而子类并不实现或重写。有些具体方法可以起来工厂方法的作用。
  • 钩子方法:钩子方法也由抽象类来实现,但这只是作为一种默认的实现,一般是空的。子类应该重新实现,如果没有的话,只是说明不需要。

示例代码:


[java]
// Source code from file:  AbstractTemplate.java

package designPatterns.TemplateMethod;

public abstract class AbstractTemplate {
// abstract method
protected abstract void abstractMethod();

// hook method, provide default implementation
protected void hookMethod() {
System.out.println("AbstractTemplate.hookMethod()");
}

// template method
public void templateMethod() {
abstractMethod();
hookMethod();
}
}

// Source code from file:  ConcreteClassA.java

package designPatterns.TemplateMethod;

public class ConcreteClassA extends AbstractTemplate {

protected void abstractMethod() {
System.out.println("ConcreteClassA.abstractMethod()");
}

protected void hookMethod() {
System.out.println("ConcreteClassA.hookMethod()");
}

}

// Source code from file:  ConcreteClassB.java

package designPatterns.TemplateMethod;

public class ConcreteClassB extends AbstractTemplate {

protected void abstractMethod() {
System.out.println("ConcreteClassB.abstractMethod()");
}

}

// Source code from file:  User.java

package designPatterns.TemplateMethod;

public class User {
public static void main(String[] args) {
AbstractTemplate a = new ConcreteClassA();
AbstractTemplate b = new ConcreteClassB();
a.templateMethod();
b.templateMethod();
}
}
[/java]
请详细分析下面代码:<#import "/decorators/includes/macros.ftl" as m> <#assign ww = JspTaglibs["/WEB-INF/webwork.tld"] /> <#include "/template/includes/actionerrors.ftl"> <#assign useStepNo=false> <#if requestForm.stepForms?exists> <#list requestForm.stepForms as stepForm> <#if stepForm.stepNo?exists> <#assign useStepNo=true> </#if> </#list> </#if> <script> document.onkeydown = function() { if(event.keyCode==116) { event.keyCode=0; event.returnValue = false; } if ((window.event.altKey)&&(window.event.keyCode==115)){ //屏蔽Alt+F4 event.keyCode=0; event.returnValue=false; alert("Please do not exit like this again. This case maybe have some problem cause of the action.Please check it.\r\n 请下次不要再这样退出。由于你的这个动作,这个单子可能已经产生了错误,请检查。"); return false; } if ((event.ctrlKey)&&(event.keyCode==87)){ //屏蔽 Ctrl+n event.keyCode=0; event.returnValue=false; return false; } } //document.oncontextmenu = function() {event.returnValue = false;} function continueRuncard(){ var date = new Date(); var minute=date.getMinutes(); if(parseInt(minute)>=0 && parseInt(minute)<=5) { alert("整点系统同步中.\n请稍后再试!"); return false; } var compareResultComment=document.getElementById("compareResultComment"); if (compareResultComment!=null){ confineStringLength(compareResultComment,500); if(compareResultComment.value==""){ return false; } } var form = document.forms['']; form.action="continueRuncard.action"; form.submit(); } function cancelRuncard(){ var date = new Date(); var minute=date.getMinutes(); if(parseInt(minute)>=0 && parseInt(minute)<=5) { alert("整点系统同步中.\n请稍后再试!"); return false; } var form = document.forms['']; form.action="cancelRuncard.action"; form.submit(); } function compareWithMes(){ <#if Rework> alert("Because RunCard's category is rework. \r\n System will not execute this function!"); return false; </#if> var form = document.forms['submitRequestFormForm']; if(!confirm("Do you want to create the comparison with MES document?\n你是否需要E-RC与MES做对比?\n\n确定 = E-RC对比MES(此动作可能需要花费几分钟时间,请耐心等待)\n\n取消 = E-RC不比对MES")){ return false; } form.action="eRuncardRule.action"; form.submit(); } function submitRunCard(){ var compareResultComment=document.getElementById("compareResultComment"); if (compareResultComment!=null){ confineStringLength(compareResultComment,500); if(compareResultComment.value==""){ return false; } } var date = new Date(); var minute=date.getMinutes(); if(parseInt(minute)>=0 && parseInt(minute)<=5) { alert("整点系统同步中.\n请稍后再试!"); return false; } disableButton(); var f=document.submitRequestFormForm; f.action = "submitRequestForm.action"; var xmlHttp = XmlHttp.create(); var async = false; xmlHttp.open("GET", "checkStepNoExistInFecp.action?lotId=${requestForm.lotId?if_exists}&holdStepNo=${requestForm.holdStepNo?if_exists}", async); xmlHttp.send(null); if(xmlHttp.responseText != null && xmlHttp.responseText == '<success/>'){ if (!confirm("你确认是否需要在这步做STR/MSTR and Link STR/MSTR \nNumber? If yes, 请确认E-runcard condition exactly \n match with FECP/STR, MSTR system\n\n确定 = 确认 Link STR/MSTR Number, submit E-runcard \n\n取消 = 修改 E-runcard")){ f.action = "viewUpdateRequestForm.action"; //f.submit(); } f.submit(); }else if(xmlHttp.responseXML != null && xmlHttp.responseXML.getElementsByTagName("success").length > 0){ if (!confirm("你确认是否需要在这步做STR/MSTR and Link STR/MSTR \nNumber? If yes, 请确认E-runcard condition exactly \n match with FECP/STR, MSTR system\n\n确定 = 确认 Link STR/MSTR Number, submit E-runcard \n\n取消 = 修改 E-runcard")){ f.action = "viewUpdateRequestForm.action"; //f.submit(); } f.submit(); }else{ f.submit(); } } </script> <@ww.form name="'submitRequestFormForm'" namespace="'/user'" validate="'true'" method="'post'" theme="'simple'"> <@ww.hidden name="'requestFormId'" value="${requestForm.id}"/> <@ww.token name="submitToken"/> <div class="app"> <h3>View e-Runcard Request Form</h3> <table border="0" cellspacing="1" cellpadding="8" width="100%"> <tr class="b"> <td>RunCard No.:</td> <td>${requestForm.caseNo?if_exists}</td> <td>Status:</td> <td><font color="red">${requestForm.status?if_exists}</font></td> </tr> <tr class="b"> <td>Applicant:</td> <td><@m.directoryLink requestForm.applicant?if_exists/> </td> <td>Organization:</td> <td>${requestForm.applicantOrg?if_exists}</td> </tr> <tr class="b"> <td>Submit Date:</td> <td>${requestForm.submitDate?if_exists}</td> <td>Effective Date:</td> <td>${requestForm.effectiveDate?if_exists}</td> </tr> <#include "viewIncludeLotInfo.ftl"/> <#include "viewIncludeSignInfo.ftl"/> <#include "viewIncludeErcHeaderInfo.ftl"/> <#include "viewIncludeErcCompleteInfo.ftl"/> <#switch requestForm.formType> <#case "Auto Reposition Step"> <#break> <#default> <table border="0" cellspacing="1" cellpadding="8" width="100%"> <tr> <th colspan="4">RunCard Steps Information</th> </tr> <#assign showWGAction = true > <#include "stepForm/includeStepForm.ftl"/> </table> </#switch> </table> <hr/> <#if requestForm.match?default("")=="N"> <table border="0" cellspacing="1" cellpadding="8" width="100%"> <tr class="b"> <td>Compare Result Comment <BR>请输入原因(Only 500 characters)</td> <td><@ww.textarea name="'requestForm.compareResultComment'" id="compareResultComment" cols="80" rows="5" theme="'simple'"/></td> </tr> </table> </#if> <table width="100%"> <tr> <td class="center"> <#if requestForm.formType="Normal"> <input type="button" onclick="compareWithMes()" value="Compare"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> <#if requestForm.haveQtime?exists> <#if requestForm.haveQtime=="Y"> <#if requestForm.formType!="Scan Defect"> <#if requestForm.formType="Normal" && useStepNo && requestForm.match=="No Comparison" && !Rework> <input type="button" class="btn" value="Continue Runcard" onclick="alert('please compare runcard first.');"/>&nbsp;&nbsp;&nbsp;&nbsp; <#else> <input type="button" class="btn" value="Continue Runcard" onclick="continueRuncard()"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> </#if> <input type="button" class="btn" value="Cancel Runcard" onclick="cancelRuncard()"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> <#else> <#if requestForm.formType="Normal" && useStepNo && requestForm.match=="No Comparison" && !Rework> <input type="button" class="btn" value="Submit" onclick="alert('please compare runcard first.');"/>&nbsp;&nbsp;&nbsp;&nbsp; <#else> <input type="button" class="btn" value="Submit" onclick="submitRunCard()"/>&nbsp;&nbsp;&nbsp;&nbsp; </#if> <input type="button" class="btn" value="Back" onclick="document.location.href='${req.contextPath}/user/viewUpdateRequestForm.action?requestFormId=${requestForm.id}'"/> </#if> </td> </tr> </table> <div> </@ww.form>
最新发布
09-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值