设计模式 行为型模式 -- 模板方法模式(定义示例JDK源码解析 InputStream)
Posted Z && Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式 行为型模式 -- 模板方法模式(定义示例JDK源码解析 InputStream)相关的知识,希望对你有一定的参考价值。
1. 模板方法模式概述
2. 模板方法模式定义
3. 模板方法模式结构
4.【例】炒菜
炒菜的步骤是固定的,分为倒油、热油、倒蔬菜、倒调料品、翻炒等步骤。现通过模板方法模式来用代码模拟。类图如下:
代码如下:
AbstractClass.java
package com.tian.template;
/**
* @version v1.0
* @ClassName: AbstractClass
* @Description: 抽象类(定义模板方法和基本方法)
*/
public abstract class AbstractClass {
//模板方法定义
public final void cookProcess() {
pourOil();
heatOil();
pourVegetable();
pourSauce();
fry();
}
public void pourOil() {
System.out.println("倒油");
}
//第二步:热油是一样的,所以直接实现
public void heatOil() {
System.out.println("热油");
}
//第三步:倒蔬菜是不一样的(一个下包菜,一个是下菜心)
public abstract void pourVegetable();
//第四步:倒调味料是不一样
public abstract void pourSauce();
//第五步:翻炒是一样的,所以直接实现
public void fry() {
System.out.println("炒啊炒啊炒到熟啊");
}
}
ConcreteClass_BaoCai.java
package com.tian.template;
/**
* @version v1.0
* @ClassName: ConcreteClass_BaoCai
* @Description: 炒包菜类(具体子类)
*/
public class ConcreteClass_BaoCai extends AbstractClass {
public void pourVegetable() {
System.out.println("下锅的蔬菜是包菜");
}
public void pourSauce() {
System.out.println("下锅的酱料是辣椒");
}
}
ConcreteClass_CaiXin.java
package com.tian.template;
/**
* @version v1.0
* @ClassName: ConcreteClass_BaoCai
* @Description: 炒菜心类(具体子类)
*/
public class ConcreteClass_CaiXin extends AbstractClass {
public void pourVegetable() {
System.out.println("下锅的蔬菜是菜心");
}
public void pourSauce() {
System.out.println("下锅的酱料是蒜蓉");
}
}
Client.java
package com.tian.template;
/**
* @version v1.0
* @ClassName: Client
* @Description:客户端类:测试类
*/
public class Client {
public static void main(String[] args) {
//炒包菜
//创建对象
ConcreteClass_BaoCai baoCai = new ConcreteClass_BaoCai();
//调用炒菜的功能
baoCai.cookProcess();
}
}
4.1 运行结果
5. 优缺点分析和适用环境
5.1 优点
5.2 缺点
5.3 适用场景
- 算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
- 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。
6. JDK源码解析
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)
方法,所以在此处重点看的方法是带三个参数的方法。
总结如下: 在InputStream
父类中已经定义好了读取一个字节数组数据的方法是每次读取一个字节,并将其存储到数组的第一个索引位置,读取len个字节数据。具体如何读取一个字节数据呢?由子类实现。
以上是关于设计模式 行为型模式 -- 模板方法模式(定义示例JDK源码解析 InputStream)的主要内容,如果未能解决你的问题,请参考以下文章