关于模板方法的定义:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法的类图比较简单,这里就不画出来了。有需要的可以上网Google一下。我们直接看例子。
现在需求要实现学生A与学生B做同一份试卷。
大量Ctrl C+Ctrl V
//学生A的试卷
public class TestPaperA {
public void testQuestion1(){
System.out.println("杨过得到,后来给了郭靖,炼成了倚天剑、屠龙刀的玄铁可能是[]");
System.out.println("a.球魔铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
System.out.println("答案是:A");
}
public void testQuestion2(){
System.out.println("杨过、程英、陆无双铲除了情花,造成[]");
System.out.println("a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
System.out.println("答案是:B");
}
}
//学生B的试卷
public class TestPaperB {
public void testQuestion1(){
System.out.println("杨过得到,后来给了郭靖,炼成了倚天剑、屠龙刀的玄铁可能是[]");
System.out.println("a.球魔铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
System.out.println("答案是:C");
}
public void testQuestion2(){
System.out.println("杨过、程英、陆无双铲除了情花,造成[]");
System.out.println("a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
System.out.println("答案是:C");
}
}
//客户端测试代码
public class Client {
public static void main(String[] args) {
System.out.println("学生A的试卷");
TestPaperA studentA = new TestPaperA();
studentA.testQuestion1();
studentA.testQuestion2();
System.out.println();
System.out.println("学生B的试卷");
TestPaperB studentB = new TestPaperB();
studentB.testQuestion1();
studentB.testQuestion2();
}
}
结果显示:
很容易就发现,学生A试卷与学生B试卷的代码十分相似,除了答案不同,没什么不一样。大量的Ctrl+C与Ctrl+V只会给维护的时候带来难以预计的灾难。
可以通过继承能提取大量相同的代码,
而使用模板方法就进一步上升了继承的高度:
当我们要完成某一细节层次一致的一个过程或者一系列步骤,但个别步骤更详细的层次上的实现可能有不同时,我们通常会考虑用模板方法模式来处理。
上面做试卷的例子,学生A与学生B除了答案所有东西都一模一样,连题目的顺序也一样,因为我们可以把这些相同的东西通通抽取成一个模板。
使用模板方法模式
public abstract class TestPaper {
public final void testQuestion1(){
System.out.println("杨过得到,后来给了郭靖,炼成了倚天剑、屠龙刀的玄铁可能是[]");
System.out.println("a.球魔铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
System.out.println("答案是:"+answer1());
}
public abstract String answer1();
public abstract String answer2();
public final void testQuestion2(){
System.out.println("杨过、程英、陆无双铲除了情花,造成[]");
System.out.println("a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
System.out.println("答案是:"+answer2());
}
public final void template(){
testQuestion1();
testQuestion2();
}
}
学生A与学生B的试卷:
public class TestPaperA extends TestPaper{
@Override
public String answer1() {
return "A";
}
@Override
public String answer2() {
return "B";
}
}
public class TestPaperB extends TestPaper{
@Override
public String answer1() {
return "C";
}
@Override
public String answer2() {
return "C";
}
}
客户端测试代码:
public class Client {
public static void main(String[] args) {
System.out.println("学生A的试卷");
TestPaper a = new TestPaperA();
a.template();
System.out.println("=======================无敌分界线==========================");
System.out.println("学生B的试卷");
TestPaper b = new TestPaperB();
b.template();
}
}
经改造后,学生A与学生B的试卷变得十分简洁,只省下答案,因为只有答案是变化的。
其中一条设计原则是:
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。简称提取公共的东西,封装变化的东西。
而模板方法模式把这些不变的行为搬到单一的地方,并定义好与变化的行为的步骤,这样就帮助子类摆脱重复的行为,又能实现相同的算法。
===============================================无敌分界线==============================================
通过研究Spring的HibernateTemplate源代码,可以发现HibernateTemplate也是借助了模板方法模式的思想。
在设计模式一书中对于模板模式GOF给出了用抽象类来实现,而spring却偏偏把它抽象到
了接口的层次。使其具有更高的扩展性,这就是一种创新的做法。
仿照Spring HibernateTemplate的思想,重新改造上面试卷的例子。
模板方法的升级
把变化的行为抽象成一个接口
public interface Answer {
public String answer1();
public String answer2();
}
模板不再是一个抽象类,而是一个具体类,因为已经不需要继承!而接口就作为参数传入模板的方法中public class TestPaper {
public final void testQuestion1(Answer answer){
System.out.println("杨过得到,后来给了郭靖,炼成了倚天剑、屠龙刀的玄铁可能是[]");
System.out.println("a.球魔铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
System.out.println("答案是:"+answer.answer1());
}
public final void testQuestion2(Answer answer){
System.out.println("杨过、程英、陆无双铲除了情花,造成[]");
System.out.println("a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
System.out.println("答案是:"+answer.answer2());
}
public final void template(Answer answer){
testQuestion1(answer);
testQuestion2(answer);
}
}
注意:也可以用组合的方式代替传参数,至于模板选择哪种方式就取决于你的需求
public class TestPaper2 {
private Answer answer;
public TestPaper2(Answer answer){
this.answer = answer;
}
private final void testQuestion1(){
System.out.println("杨过得到,后来给了郭靖,炼成了倚天剑、屠龙刀的玄铁可能是[]");
System.out.println("a.球魔铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
System.out.println("答案是:"+answer.answer1());
}
private final void testQuestion2(){
System.out.println("杨过、程英、陆无双铲除了情花,造成[]");
System.out.println("a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
System.out.println("答案是:"+answer.answer2());
}
public final void template(){
testQuestion1();
testQuestion2();
}
}
学生A与学生B只需要实现Answer接口(变化的部分)即可
public class TestPaperA implements Answer{
public String answer1() {
return "A";
}
public String answer2() {
return "B";
}
}
public class TestPaperB implements Answer{
public String answer1() {
return "C";
}
public String answer2() {
return "C";
}
}
客户端测试代码:
public class Client {
public static void main(String[] args) {
TestPaper testPaper = new TestPaper();
Answer a = new TestPaperA();
System.out.println("学生A的考卷");
testPaper.template(a);
System.out.println("=====================无敌分界线========================");
System.out.println("学生B的考卷");
Answer b = new TestPaperB();
testPaper.template(b);
}
}
显示结果:略
(第2种模板的测试代码略)
总结一下这种做法的优点:
1)由于Java不支持多重继承,所以采用模板方法时,子类继承模板会有诸多限制,而采用接口代替抽象类来封装变化,不但是一种创新的做法,而且使模板方法模式更加灵活,能适用于更多需求。
2)继承只能在编译时就决定(静态),而采用委托的方式可以在运行时去改变行为(动态)
3)有时候子类会被调用得十分频繁,如果每调用一次就继承一个庞大的模板,这显然十分笨重。用接口代替抽象类配合模板方法,既达到了代码服用的效果,又能轻松实现某些特定步骤。
- 大小: 36.2 KB
分享到:
相关推荐
在软件设计领域,设计模式是解决常见问题的模板,提供了可重用的解决方案。本案例主要探讨了三种经典的设计模式:抽象工厂模式、工厂方法模式和策略模式,并以手机加工厂为实际应用场景进行阐述。 首先,**抽象工厂...
模板方法模式是一种行为设计模式,它允许在定义行为的同时延迟一些具体步骤到子类中实现。这种模式在JavaScript中尤其有用,因为它可以帮助我们组织代码,减少重复,并提供了一种优雅的方式来处理共同的算法框架。 ...
在模板方法模式中,我们通常会有一个抽象类(模板类),它定义了一个模板方法,这个方法包含了一系列步骤,其中某些步骤被声明为抽象的或者使用钩子(hook)方法来实现。子类继承模板类并实现这些抽象方法或覆盖钩子...
网页模板(B/S管理框架模板)是一种基于浏览器-服务器(Browser/Server)架构的网页设计模式,它主要用于构建高效、易维护的管理界面。新模式设计概念则代表了在这一领域不断演进的创新思想,旨在提供更为直观、用户...
4. **模板方法模式(10模板方法模式)**:在模板方法模式中,定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 5. **命令模式(23命令模式...
对于“IE浏览器版本过低提示”模板页,开发者会确保其简洁明了,突出升级浏览器的必要性,并提供明确的操作指引。 压缩包中的"ie.html"很可能是这个提示页面的源代码,通过查看它的内容,我们可以了解如何检测...
- 区块(Block)是模板的一部分,可以被重定义或覆盖,提供了一种模块化的方法来管理模板结构。 6. **模板调试与优化**: - 开发者工具:可能有专门的模板调试模式,帮助开发者查看编译后的PHP代码,定位问题。 ...
在使用或升级模板前,最好先备份现有数据,并在测试环境中预览模板效果。 9. **维护与更新**:随着时间推移,可能需要更新模板以适应 Destoon 系统的新版本或满足新的功能需求。保持模板的更新可以确保网站的稳定...
Vue.js是一个轻量级的渐进式框架,它提供了组件化开发模式,便于代码组织和复用。Vue.js的响应式数据绑定和虚拟DOM技术使得CRMEB模板在页面更新时能高效地计算和更新视图,从而提升用户体验。此外,Vue.js还有丰富的...
《创新模式十二宫:后互联网时代企业创新升级路线图》这本书提供了一套全面的方法论,旨在帮助企业理解在互联网浪潮过后的新环境下如何进行创新与转型。它以商业画布为载体,构建了一个十二宫格的创新模型,涵盖了...
设计模式是一种在特定情况下解决软件设计问题的最佳实践,它为程序员提供了在类似情况下重复使用解决方案的模板。 首先,我们来看一下“简单工厂模式”(Simple Factory Pattern)。这种模式的核心思想是提供一个...
这篇详细的知识点解析将指导你如何将基于 Vue CLI 2 的项目手动升级到使用 Webpack 4 的项目模板。 1. **Webpack 4 的主要变化**: - **性能提升**:Webpack 4 引入了更快的编译速度和更小的打包体积,这得益于对 ...
模板设计上,"经典模板"通常意味着其遵循了用户熟悉的布局和设计模式,易于导航,有助于提高用户体验。橙色作为主色调,象征活力、热情和积极,可以激发消费者的购买欲望,同时也能使网站在众多电商网站中脱颖而出。...
包括责任链模式、命令模式、解释器模式、迭代器模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。它们可以帮助我们更好地管理复杂系统的动态行为。 每一种设计模式都有其特定的适用...
包括责任链模式(Chain of Responsibility)、命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者模式(Mediator)...Strategy)、模板方法模式(Template Method)和访问者模式(Visitor)...
在Java中,设计模式的应用不仅限于上述介绍,还包括其他如命令模式(Command)、迭代器模式(Iterator)、备忘录模式(Memento)、模板方法模式(Template Method)等。这些模式在设计复杂系统时起着关键作用,比如...
ASPX是ASP (Active Server Pages) 的升级版本,引入了更强大的功能和改进的语法。在ASPX页面中,开发者可以使用C#或VB.NET等.NET支持的语言编写代码,这些代码被嵌入到HTML标记中,通过服务器控件和数据绑定技术实现...
因此,使用模板的同时,也需要关注ECShop的版本更新,适时进行模板的适配和升级。 8. 常见问题与解决:在部署和使用模板过程中,可能会遇到兼容性问题、错误提示等,需要开发者具备一定的问题排查和解决能力,可以...
- **行为型模式**:关注对象间的职责分配,如策略模式、模板方法模式、观察者模式、命令模式、迭代器模式、中介者模式、备忘录模式、状态模式、访问者模式和解释器模式。 #### 设计模式的价值 设计模式的价值不仅...
总的来说,"自助下单系统免授权 多模板+小储云商城模板.zip" 提供了一整套完善的电子商务解决方案,无论你是刚刚涉足电商的新手,还是正在寻求升级现有系统的商家,都能从中受益。通过利用这个系统,商家不仅可以...