今日练习两个工作中经常会使用到的设计模式,分别是模板方法模式和责任链模式。下面将从定义、类型、特点、优缺点以及实际Coding等角度进行说明。
目录
模板方法模式
定义:定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现。
特点:模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。
类型:行为型
适用场景:
- 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为被提取出来并集中到一个公共父类中,从而避免代码重复。
优点:
- 提高复用性
- 提高扩展性
- 符合开闭原则
缺点:
- 类数目增加
- 增加了系统实现的复杂度
- 继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍
扩展:
- 钩子方法:提供了缺省的行为,子类可以在必要时进行扩展。
Coding
模板方法类
public abstract class AbstractCourse {
final void makeCourse() {
makeVideo();
makePPT();
if(needWriteArticle()) {
writeArticle();
}
makepackage();
}
protected final void makeVideo() {
System.out.println("制作视频");
}
protected final void makePPT() {
System.out.println("制作PPT");
}
protected final void writeArticle() {
System.out.println("写手记");
}
boolean needWriteArticle() {
return false;
}
protected abstract void makepackage();
}
具体实现类A
public class JavaCourse extends AbstractCourse {
@Override
protected void makepackage() {
System.out.println("完成Java课程制作");
}
@Override
boolean needWriteArticle() {
return true;
}
}
具体实现类B
public class GoCourse extends AbstractCourse {
// 为了使用钩子函数
private boolean needWriteArticle;
@Override
protected void makepackage() {
System.out.println("完成Go课程制作");
}
public GoCourse() {
}
public GoCourse(Boolean needWriteArticle) {
this.needWriteArticle = needWriteArticle;
}
// 重写钩子函数
@Override
boolean needWriteArticle() {
return this.needWriteArticle;
}
}
测试类
public class Test {
public static void main(String[] args) {
AbstractCourse javaCourse = new JavaCourse();
javaCourse.makeCourse();
System.out.println("==========");
AbstractCourse goCourse = new GoCourse(true);
goCourse.makeCourse();
}
}
Coding体会
模板方法模式在抽象类中完成某个方法整体骨架的制定,骨架中有三类方法:固定方法;钩子方法;自定义方法。固定方法,在任何子类实现中都是一样的,而钩子方法可以对一些固定方法进行选择,自定义方法完全由各子类实现。通过实现模板方法,能方便实现代码复用和扩展,符合开闭原则。
在源码中的体现
- HttpServlet的doPost()、doGet()、service()等方法;
- MyBatis中的抽象类BaseExecutor,对应的实现类有SimpleExecutor、BatchExecutor等,都实现了doUpdate()方法。
责任链模式
定义:为请求创建一个接收此次请求对象的链
类型:行为型
适用场景:一个请求的处理需要多个对象当中的一个或几个协作处理
优点:
- 请求的发送者和接收者(请求的处理)解耦
- 责任链可以动态组合
缺点:
- 责任链太长或者处理时间过长,影响性能
- 责任链有可能过多
Coding
实体类
public class Course {
private String name;
private String article;
private String video;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
", article='" + article + '\'' +
", video='" + video + '\'' +
'}';
}
}
审批人(抽象类,责任链模式的核心类)
public abstract class Approver {
protected Approver approver;
public Approver() {
}
public Approver(Approver approver) {
this.approver = approver;
}
public Approver getApprover() {
return approver;
}
public void setApprover(Approver approver) {
this.approver = approver;
}
protected abstract void approve(Course course);
}
实现类A
import org.apache.commons.lang.StringUtils;
public class ArticleApprover extends Approver{
@Override
protected void approve(Course course) {
if (StringUtils.isNotEmpty(course.getArticle())) {
System.out.println(course.getName() + "含有手记,批准!");
if (approver != null) {
approver.approve(course);
}
} else {
System.out.println(course.getName() + "不含有手记,不批准,结束流程!");
}
}
}
实现类B
import org.apache.commons.lang.StringUtils;
public class VideoApprover extends Approver {
@Override
protected void approve(Course course) {
if (StringUtils.isNotEmpty(course.getVideo())) {
System.out.println(course.getName() + "含有视频,批准!");
if (approver != null) {
approver.approve(course);
}
} else {
System.out.println(course.getName() + "不含有视频,不批准,流程结束!");
}
}
}
测试类
public class Test_Responsibility_Chain {
public static void main(String[] args) {
Approver articleApprover = new ArticleApprover();
Approver videoApprover = new VideoApprover();
Course course = new Course();
course.setName("Java课程");
course.setArticle("Java手记");
course.setVideo("Java视频");
articleApprover.setApprover(videoApprover);
articleApprover.approve(course);
}
}
Coding体会
责任链模式的核心思想在于链式主体中含有一个当前主体的对象,并且含有一个抽象方法,交由不同的实例进行具体实现。
在源码中的体现
- Servlet中的FilterChain(过滤器)是链式实现,具体的实现类:MockFilterChain等
例如,在LoggerContextFilter中有一个doFilter方法,会传参FilterChain,然后在方法实现中,会再次调用传的FilterChain的doFilter方法。
- SpringSecurity中应用了很多责任链