网站建设中asp文件,网站开发流程中客户的任务是什么,信息产业部备案网站,网站建设及发布的流程行为型模式用于描述程序在运行时复杂的流程控制#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务#xff0c;它涉及算法与对象间职责的分配。
行为型模式分为类行为模式和对象行为模式#xff0c;前者采用继承机制来在类间分派行为即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务它涉及算法与对象间职责的分配。
行为型模式分为类行为模式和对象行为模式前者采用继承机制来在类间分派行为后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低满足“合成复用原则”所以对象行为模式比类行为模式具有更大的灵活性。
行为型模式分为 模板方法模式 策略模式 命令模式 职责链模式 状态模式 观察者模式 中介者模式 迭代器模式 访问者模式 备忘录模式 解释器模式
以上 11 种行为型模式除了模板方法模式和解释器模式是类行为型模式其他的全部属于对象行为型模式。
1 模板方法模式
1.1 概述
在面向对象程序设计过程中程序员常常会遇到这种情况设计一个系统时知道了算法所需的关键步骤而且确定了这些步骤的执行顺序但某些步骤的具体实现还未知或者说某些步骤的实现与具体的环境相关。
例如去银行办理业务一般要经过以下4个流程取号、排队、办理具体业务、对银行工作人员进行评分等其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的可以在父类中实现但是办理具体业务却因人而异它可能是存款、取款或者转账等可以延迟到子类中实现。
定义
定义一个操作中的算法骨架而将算法的一些步骤延迟到子类中使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
1.2 结构
模板方法Template Method模式包含以下主要角色 抽象类Abstract Class负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。 模板方法定义了算法的骨架按某种顺序调用其包含的基本方法。 基本方法是实现算法各个步骤的方法是模板方法的组成部分。基本方法又可以分为三种 抽象方法(Abstract Method) 一个抽象方法由抽象类声明、由其具体子类实现。 具体方法(Concrete Method) 一个具体方法由一个抽象类或具体类声明并实现其子类可以进行覆盖也可以直接继承。 钩子方法(Hook Method) 在抽象类中已经实现包括用于判断的逻辑方法和需要子类重写的空方法两种。 一般钩子方法是用于判断的逻辑方法这类方法名一般为isXxx返回值类型为boolean类型。 具体子类Concrete Class实现抽象类中所定义的抽象方法和钩子方法它们是一个顶级逻辑的组成步骤。
1.3 案例实现
【例】炒菜
炒菜的步骤是固定的分为倒油、热油、倒蔬菜、倒调料品、翻炒等步骤。现通过模板方法模式来用代码模拟。类图如下 代码如下
//抽象类定义模板方法和基本方法
public abstract class AbstractClass {// 模板方法public final void cookProcess() {//第一步倒油this.pourOil();//第二步热油this.heatOil();//第三步倒蔬菜this.pourVegetable();//第四步倒调味料this.pourSauce();//第五步翻炒this.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(炒啊炒啊炒到熟啊);}
}
public class ConcreteClass_BaoCai extends AbstractClass {
Overridepublic void pourVegetable() {System.out.println(下锅的蔬菜是包菜);}
Overridepublic void pourSauce() {System.out.println(下锅的酱料是辣椒);}
}
public class ConcreteClass_CaiXin extends AbstractClass {Overridepublic void pourVegetable() {System.out.println(下锅的蔬菜是菜心);}
Overridepublic void pourSauce() {System.out.println(下锅的酱料是蒜蓉);}
}
public class Client {public static void main(String[] args) {//炒手撕包菜ConcreteClass_BaoCai baoCai new ConcreteClass_BaoCai();baoCai.cookProcess();System.out.println();//炒蒜蓉菜心ConcreteClass_CaiXin caiXin new ConcreteClass_CaiXin();caiXin.cookProcess();}
} 注意为防止恶意操作一般模板方法都加上 final 关键词。 1.4 优缺点
优点 提高代码复用性 将相同部分的代码放在抽象的父类中而将不同的代码放入不同的子类中。 实现了反向控制 通过一个父类调用其子类的操作通过对子类的具体实现扩展不同的行为实现了反向控制 并符合“开闭原则”。
缺点 对每个不同的实现都需要定义一个子类这会导致类的个数增加系统更加庞大设计也更加抽象。 父类中的抽象方法由子类实现子类执行的结果会影响父类的结果这导致一种反向的控制结构它提高了代码阅读的难度。
1.5 适用场景 算法的整体步骤很固定但其中个别部分易变时这时候可以使用模板方法模式将容易变的部分抽象出来供子类实现。 需要通过子类来决定父类算法中某个步骤是否执行实现子类对父类的反向控制。
1.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;}
//调用了无参的read方法该方法是每次读取一个字节数据// 其根本是调用子类的read方法因为read必须被子类重写// 实现子类对父类的反向控制这就是模板方法的核心思想int c 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个字节数据。具体如何读取一个字节数据呢由子类实现。