中国十大做网站公司,大连信联科技做的网站怎么样,专业做网站开发公司,《高性能网站建设指南文章目录 介绍基本介绍使用说明应用场景登场角色 案例实现案例一问题介绍实现模板方法模式的钩子方法 案例二实现 模板方法模式在IOC的源码分析总结思考思考一思考二 文章说明 介绍
基本介绍
模板方法模式#xff0c;又叫模板模式#xff0c;在一个抽象类中定义了一个执行它… 文章目录 介绍基本介绍使用说明应用场景登场角色 案例实现案例一问题介绍实现模板方法模式的钩子方法 案例二实现 模板方法模式在IOC的源码分析总结思考思考一思考二 文章说明 介绍
基本介绍
模板方法模式又叫模板模式在一个抽象类中定义了一个执行它的其他方法的公开模板方法子类可以按需重写抽象类的抽象方法简单说模板方法模式 定义一个操作中的算法或者说流程的骨架而将一些步骤下放到子类中实现使得子类可以在不改变算法结构的基础上可以重新定义算法的某些步骤该模式属于行为型模式
使用说明 【AbstractClass】
template方法规定了如何调用operation2、operation3、operation4这几个子方法子方法可以是抽象方法需要子类来实现也可以是已经实现的方法
【ConcreteClass、ConcreteClassB】
用来实现父类的抽象方法
应用场景
当要完成某个过程该过程要执行一系列步骤这一系列的步骤基本相同但其个别步骤可能有不同的实现通常考虑用模板方法模式来处理
登场角色
AbstractClass(抽象类)该角色负责实现模板方法还声明在模板方法中所使用到的抽象方法ConcreteClass(具体类)负责具体实现AbstractClass角色中定义的抽象方法。这里实现的方法将会在AbstractClass角色的模板方法中被调用Client(客户端)使用具体类继承的模板方法
案例实现
案例一
问题介绍
编写制作豆浆的程序说明如下
通过添加不同的配料可以制作出不同口味的豆浆制作豆浆的流程选材—添加配料—浸泡—放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的
实现
【豆浆抽象类】
package com.atguigu.template;/*** 抽象类表示豆浆*/
public abstract class SoyaMilk {/*** 模板方法, 模板方法可以做成final , 不让子类去覆盖*/final void make() {select();addCondiments();soak();beat();}/*** 选材料*/void select() {System.out.println(第一步选择好的新鲜黄豆 );}/*** 添加不同的配料 抽象方法, 子类具体实现*/abstract void addCondiments();/*** 浸泡*/void soak() {System.out.println(第三步黄豆和配料开始浸泡 需要3小时 );}/*** 打碎*/void beat() {System.out.println(第四步黄豆和配料放到豆浆机去打碎 );}
}【红豆豆浆】
package com.atguigu.template;/*** 红豆豆浆*/
public class RedBeanSoyaMilk extends SoyaMilk {Overridevoid addCondiments() {System.out.println( 加入上好的红豆 );}}【花生豆浆】
package com.atguigu.template;/*** 花生豆浆*/
public class PeanutSoyaMilk extends SoyaMilk {Overridevoid addCondiments() {System.out.println( 加入上好的花生 );}}【主类】
package com.atguigu.template;public class Client {public static void main(String[] args) {System.out.println(----制作红豆豆浆----);SoyaMilk redBeanSoyaMilk new RedBeanSoyaMilk();redBeanSoyaMilk.make();System.out.println(----制作花生豆浆----);SoyaMilk peanutSoyaMilk new PeanutSoyaMilk();peanutSoyaMilk.make();}}【运行】
----制作红豆豆浆----
第一步选择好的新鲜黄豆 加入上好的红豆
第三步黄豆和配料开始浸泡 需要3小时
第四步黄豆和配料放到豆浆机去打碎
----制作花生豆浆----
第一步选择好的新鲜黄豆 加入上好的花生
第三步黄豆和配料开始浸泡 需要3小时
第四步黄豆和配料放到豆浆机去打碎 Process finished with exit code 0模板方法模式的钩子方法
在模板方法模式的父类中我们可以定义一个方法它默认不做任何事子类可以视情况要不要覆盖它该方法称为“钩子”。
应用场景希望可以制作纯豆浆需要添加任何配料使用钩子方法改造上面的程序
【豆浆抽象类】
package com.atguigu.template.improve;//抽象类表示豆浆
public abstract class SoyaMilk {/*** 模板方法, make , 模板方法可以做成final , 不让子类去覆盖.*/final void make() {select();if(customerWantCondiments()) {// 如果需要添加配料addCondiments();}soak();beat();}/*** 选材料*/void select() {System.out.println(第一步选择好的新鲜黄豆 );}/*** 添加不同的配料 抽象方法, 子类具体实现*/abstract void addCondiments();/*** 浸泡*/void soak() {System.out.println(第三步黄豆和配料开始浸泡 需要3小时 );}/*** 打碎*/void beat() {System.out.println(第四步黄豆和配料放到豆浆机去打碎 );}/*** 钩子方法决定是否需要添加配料* return*/boolean customerWantCondiments() {return true;}
}【纯豆浆】
package com.atguigu.template.improve;/*** 纯豆浆*/
public class PureSoyaMilk extends SoyaMilk{Overridevoid addCondiments() {//空实现}/*** 如果需要自定义钩子函数就重写这个方法不需要就不用重写* return*/Overrideboolean customerWantCondiments() {return false;}}【主类】
package com.atguigu.template.improve;public class Client {public static void main(String[] args) {System.out.println(----制作纯豆浆----);SoyaMilk pureSoyaMilk new PureSoyaMilk();pureSoyaMilk.make();}}【运行】
----制作纯豆浆----
第一步选择好的新鲜黄豆
第三步黄豆和配料开始浸泡 需要3小时
第四步黄豆和配料放到豆浆机去打碎 Process finished with exit code 0案例二 实现
【抽象类】
package com.atguigu.template.Sample;/*** 抽象类AbstractDisplay*/
public abstract class AbstractDisplay {/*** 交给子类去实现的抽象方法(1) open*/public abstract void open();/*** 交给子类去实现的抽象方法(2) print*/public abstract void print();/*** 交给子类去实现的抽象方法(3) close*/public abstract void close();/*** 本抽象类中实现的display方法模板方法*/public final void display() {// 首先打开…open();// 循环调用5次printfor (int i 0; i 5; i) {print();}// …最后关闭。这就是display方法所实现的功能close();}
}【子类CharDisplay】
package com.atguigu.template.Sample;/*** CharDisplay是AbstractDisplay的子类*/
public class CharDisplay extends AbstractDisplay {/*** 需要显示的字符*/private char ch;public CharDisplay(char ch) {// 保存在字段中this.ch ch;}public void open() {// 显示开始字符System.out.print();}public void print() {// 显示保存在字段ch中的字符System.out.print(ch);}public void close() {// 显示结束字符System.out.println();}
}【子类StringDisplay】
package com.atguigu.template.Sample;/*** StringDisplay也是AbstractDisplay的子类*/
public class StringDisplay extends AbstractDisplay {/*** 需要显示的字符串*/private String string;/*** 以字节为单位计算出的字符串长度*/private int width;public StringDisplay(String string) {this.string string;// 将字符串的字节长度也保存在字段中以供后面使用this.width string.getBytes().length;}public void open() {// 调用该类的printLine方法画线printLine();}public void print() {// 给保存在字段中的字符串前后分别加上|并显示出来System.out.println(| string |);}public void close() {// 与open方法一样调用printLine方法画线printLine();}/*** 被open和close方法调用。由于可见性是private因此只能在本类中被调用*/private void printLine() {// 显示表示方框的角的System.out.print(); for (int i 0; i width; i) {// 显示width个-,和一起组成边框System.out.print(-); }// 显示表示方框的角的System.out.println(); }
}【主类】
package com.atguigu.template.Sample;public class Main {public static void main(String[] args) {// 生成一个持有H的CharDisplay类的实例 AbstractDisplay d1 new CharDisplay(H);// 生成一个持有Hello, world.的StringDisplay类的实例 AbstractDisplay d2 new StringDisplay(Hello, world.);// 生成一个持有你好世界。的StringDisplay类的实例 AbstractDisplay d3 new StringDisplay(你好世界。);/** 由于d1、d2和d3都是AbstractDisplay类的子类* 可以调用继承的display方法* 实际的程序行为取决于CharDisplay类和StringDisplay类的具体实现*/d1.display();d2.display();d3.display();}}【运行】
HHHHH
-------------
|Hello, world.|
|Hello, world.|
|Hello, world.|
|Hello, world.|
|Hello, world.|
-------------
------------------
|你好世界。|
|你好世界。|
|你好世界。|
|你好世界。|
|你好世界。|
------------------Process finished with exit code 0模板方法模式在IOC的源码分析 实现类有一个模板方法 另一个钩子方法 除此之外java.io.InputStream类中也使用了Template Method
总结
【优点】
既统一了算法也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变同时由子类提供部分步骤的实现实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。如果模板方法有bug只需要修改一个类即可不使用模板方法模式的话就需要修改多个类的代码父类和子类具有一致性在示例程序中不论是CharDisplay的实例还是StringDisplay的实例都是先保存在AbstractDisplay类型的变量中然后再来调用display方法的。使用父类类型的变量保存子类实例的优点是即使没有用instanceof等指定子类的种类程序也能正常工作。无论在父类类型的变量中保存哪个子类的实例程序都可以正常工作这种原则称为里氏替换原则
【不足】
不足每一个不同的实现都需要一个子类实现导致类的个数增加使得系统更加庞大一般模板方法都加上final关键字 防止子类重写模板方法
思考
思考一
问如果想要让示例程序中的open、print、close方法可以被具有继承关系的类和同一程序包中的类调用但是不能被无关的其他类调用应当怎么做呢?
答使用protected关键字修饰这些方法不要使用public。
【Java四种权限修饰符】
publicprotected(default)private类本身√√√√同一个包下的类√√√×不同包但是我的子类√√××不同包非子类√×××
注default不需要写出来不写权限修饰符默认就是defaunt
思考二
问Java中的接口与抽象类很相似。接口同样也是抽象方法的集合但是在模板方法模式中我们却无法使用接口来扮演AbstractClass 角色请问这是为什么呢?
答因为使用接口无法实现模板方法和其他的方法。
文章说明
本文章为本人学习尚硅谷的学习笔记文章中大部分内容来源于尚硅谷视频点击学习尚硅谷相关课程也有部分内容来自于自己的思考发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识如有侵权请联系删除最后对尚硅谷的优质课程表示感谢。本人还同步阅读《图解设计模式》书籍图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社2017.1进而综合两者的内容让知识点更加全面