旅游网站建设的现状,江门站排名优化,wordpress手机展示,住建部官网查询1.定义
定义一个操作中的算法骨架#xff0c;而将算法的一些步骤延迟到子类中#xff0c;使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
2.结构
模板方法#xff08;Template Method#xff09;模式包含以下主要角色#xff1a; 抽象类#xff0…1.定义
定义一个操作中的算法骨架而将算法的一些步骤延迟到子类中使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
2.结构
模板方法Template Method模式包含以下主要角色 抽象类Abstract Class负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。 模板方法定义了算法的骨架按某种顺序调用其包含的基本方法。 基本方法是实现算法各个步骤的方法是模板方法的组成部分。基本方法又可以分为三种 抽象方法(Abstract Method) 一个抽象方法由抽象类声明、由其具体子类实现。 具体方法(Concrete Method) 一个具体方法由一个抽象类或具体类声明并实现其子类可以进行覆盖也可以直接继承。 钩子方法(Hook Method) 在抽象类中已经实现包括用于判断的逻辑方法和需要子类重写的空方法两种。 一般钩子方法是用于判断的逻辑方法这类方法名一般为isXxx返回值类型为boolean类型。 具体子类Concrete Class实现抽象类中所定义的抽象方法和钩子方法它们是一个顶级逻辑的组成步骤。
3.案例实现
/*** author 晓风残月Lx* date 2023/7/21 16:47* 抽象类定义模板方法和基本方法*/
public abstract class AbstractClass {// 模板方法 加上final不让子类改变方法结构public final void cookProcess() {// 第一步倒油this.pourOil();// 第二步热油this.heatOil();// 第三步倒蔬菜this.pourVegetable();// 第四步倒调味料this.pourSauce();// 第五步翻炒this.fry();}// 抽象方法public abstract void pourSauce();public abstract void pourVegetable();// 具体方法private void fry() {System.out.println(翻炒);}private void heatOil() {System.out.println(热油);}private void pourOil() {System.out.println(倒油);}}
/*** author 晓风残月Lx* date 2023/7/25 0:46* 炒包菜类 具体的类*/
public class ConcreteClass_BaoCai extends AbstractClass {Overridepublic void pourSauce() {System.out.println(下锅的酱料是辣椒);}Overridepublic void pourVegetable() {System.out.println(下锅的蔬菜是包菜);}
}
/*** author 晓风残月Lx* date 2023/7/25 0:46* 炒菜芯类 具体的类*/
public class ConcreteClass_CaiXin extends AbstractClass {Overridepublic void pourSauce() {System.out.println(下锅的酱料是蒜蓉);}Overridepublic void pourVegetable() {System.out.println(下锅的蔬菜是菜芯);}
}
/*** author 晓风残月Lx* date 2023/7/25 0:48*/
public class Client {public static void main(String[] args) {// 炒包菜// 创建对象ConcreteClass_BaoCai baoCai new ConcreteClass_BaoCai();baoCai.cookProcess();// 炒菜芯ConcreteClass_CaiXin caiXin new ConcreteClass_CaiXin();caiXin.cookProcess();}
}
4.优缺点
优点 提高代码复用性 将相同部分的代码放在抽象的父类中而将不同的代码放入不同的子类中。 实现了反向控制 通过一个父类调用其子类的操作通过对子类的具体实现扩展不同的行为实现了反向控制 并符合“开闭原则”。
缺点
对每个不同的实现都需要定义一个子类这会导致类的个数增加系统更加庞大设计也更加抽象。父类中的抽象方法由子类实现子类执行的结果会影响父类的结果这导致一种反向的控制结构它提高了代码阅读的难度。
5.使用场景
算法的整体步骤很固定但其中个别部分易变时这时候可以使用模板方法模式将容易变的部分抽象出来供子类实现。需要通过子类来决定父类算法中某个步骤是否执行实现子类对父类的反向控制。
6.JDK源码解析
InputStream类就使用了模板方法模式。在InputStream类中定义了多个 read() 方法如下
public abstract class InputStream implements Closeable {//抽象方法要求子类必须重写public abstract int read() throws IOException;public int read(byte b[]) throws IOException {return read(b, 0, b.length);}public int read(byte b[], int off, int len) throws IOException {if (b null) {throw new NullPointerException();} else if (off 0 || len 0 || len b.length - off) {throw new IndexOutOfBoundsException();} else if (len 0) {return 0;}int c read(); //调用了无参的read方法该方法是每次读取一个字节数据if (c -1) {return -1;}b[off] (byte)c;int i 1;try {for (; i len ; i) {c read();if (c -1) {break;}b[off i] (byte)c;}} catch (IOException ee) {}return i;}
}从上面代码可以看到无参的 read() 方法是抽象方法要求子类必须实现。而 read(byte b[]) 方法调用了 read(byte b[], int off, int len) 方法所以在此处重点看的方法是带三个参数的方法。
在该方法中第18行、27行可以看到调用了无参的抽象的 read() 方法。
总结如下 在InputStream父类中已经定义好了读取一个字节数组数据的方法是每次读取一个字节并将其存储到数组的第一个索引位置读取len个字节数据。具体如何读取一个字节数据呢由子类实现。