https://coding.imooc.com/class/270.html
- 应用场景
提供自定义服务给应用层,但是可复用的方法自己封装起来。可复用的方法如果有属性是按需提供的,可以使用钩子方法控制。 - 相关设计模式
建造者模式是链式配置对象,把配置过程暴露在应用层。而模板模式,是把自定义的代码块封装在类里。同样是保留默认配置,提供外部自定义修改的方法,形式不同。个人认为两者可以一起用。
建造者模式
public static void main(String[] args) {
// 初始化java课程,不上传源码资源
AbstractCourse course = new JavaCourse(false);
// 初始化java课程,上传源码资源
AbstractCourse course1 = new JavaCourse(true);
// 课程上线,调用的是模板方法,不要调用到initCourse()方法
course.makeCourse();
course1.makeCourse();
// 配合建造者模式使用
AbstractCourse course2 = new JavaCourse.SourceBuilder()
.buildCodeSource(true)
.buildPrice(15)
.build();
// 课程上线,调用的是模板方法
course2.makeCourse();
}
- 实现
/**
* 抽象的网课类
* 需要新增一门网课,必须要上传PPT和课程 -- 模板
* 是否上传源码资源则为可选 -- 自定义内容
*/
public abstract class AbstractCourse {
// 创建不能给修改的方法,所以称为模板
final void makeCourse(){
upLoadPPT();
upLoadVideo();
if(needUpLoadSource()){
upLoadSource();
}
// 抽象后置方法
initCourse();
}
// PPT和视频是网课的必要元素,这两个方法作为模板
final void upLoadPPT(){
System.out.println("上传课程PPT");
}
final void upLoadVideo(){
System.out.println("上传课程视频");
}
// 源码资源可以上传也可以不上传
final void upLoadSource(){
System.out.println("上传源码资源");
}
// 钩子方法,留给外界控制模板中可变的部分
protected boolean needUpLoadSource(){
return false;
}
// 自定义代码块,给子类实现
abstract void initCourse();
}
/**
* 子类使用模板
*/
public class JavaCourse extends AbstractCourse {
boolean flag = false;
// 基础模板后必须自定义独特的部分,默认部分已经隐藏
@Override
protected void initCourse() {
System.out.println("初始化Java课程" + "售价为:"+ this.price);
}
/**
* 构造方法指定是否上传源码资源
* @param flag
*/
public JavaCourse(boolean flag){
this.flag = flag;
}
// 可以灵活得重写,外部来确定该课程是不是要上传源码资源,默认是false
@Override
protected boolean needUpLoadSource() {
// 这里覆盖父类的方法
// 第一种方法:直接修改返回值,return true;
// 第二种方法:使用构造方法给外部指定
return flag;
}
- 建造者相关
/**
* 建造者模式的构造方法
* @param sourceBuilder
*/
public JavaCourse(SourceBuilder sourceBuilder){
this.flag = sourceBuilder.flag;
this.price = sourceBuilder.price;
}
/**
* 静态内部类设置建造者
*/
public static class SourceBuilder {
// 内部类属性,与外部一致
int price = 0;
boolean flag = false;
public SourceBuilder buildPrice(int price){
this.price = price;
return this;
}
public SourceBuilder buildCodeSource(boolean flag){
this.flag = flag;
return this;
}
public JavaCourse build(){
return new JavaCourse(this);
}
}