1. 什么是模板方法模式?
定义一个操作中的算法的框架,将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重新定义该算法的某些特定步骤。
2. 模板方法结构图
3. 开始撸代码,举个连接数据库的例子(车辆模型)
3.1 创建一个AbstractClass抽象类
public abstract class AbstractClass {
protected abstract void startConnection();
protected abstract void endConnect();
public void templateMethod() {
// 调用基本方法完成相应逻辑
this.startConnection();
this.endConnect();
}
}
3.2 创建具体的连接用户
ConcreteUserA
public class ConcreteUserA extends AbstractClass{
@Override
protected void startConnection() {
System.out.println("A用户连接了数据库");
}
@Override
protected void endConnect() {
System.out.println("A用户释放了数据库");
}
}
ConcreteUserB
public class ConcreteUserB extends AbstractClass{
@Override
protected void startConnection() {
System.out.println("B用户连接了数据库");
}
@Override
protected void endConnect() {
System.out.println("B用户释放了数据库");
}
}
3.3 创建用来测试的Client类
public class Client {
public static void main(String[] args) {
// 创建一个具体用户A的模板对象
AbstractClass userA = new ConcreteUserA();
// 调用模板方法,完成连接和释放
userA.templateMethod();
AbstractClass userB = new ConcreteUserB();
userB.templateMethod();
}
}
4. 总结
模板方法的优点:
- 封装不变部分,扩展可变部分
- 提取公共代码,易于维护
- 行为由父类控制,子类实现
模板方法的缺点:
正常设计习惯,抽象类负责声明最抽象和最一般的事物属性方法,实现类完成具体的事物属性和方法。但是模板方法模式颠倒了,使得子类对父类产生了影响,会带来代码的阅读的难度。
5. 模板类的扩展
当我们对上述模板要进行部分修改,增加输入参数的灵活性,这样会导致子类改动较大,于是,在设计模式中会提出hook的概念,一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是空实现,作为方法的默认实现。
如释放连接,当完成查询任务后,我们才能释放连接,于是修改代码:
5.1 修改AbstractClass
public abstract class AbstractClass {
protected abstract void startConnection();
protected abstract void endConnect();
public void templateMethod() {
// 调用基本方法完成相应逻辑
this.startConnection();
if (!this.isBusy()) {
this.endConnect();
} else {
System.out.println("忙着呢,无法释放连接");
}
}
// 定义一个hook方法,作为方法的默认实现,默认是释放前已无其他操作
protected boolean isBusy() {
return false;
}
}
5.2 修改
ConcreteUserA
public class ConcreteUserA extends AbstractClass{
private boolean busyFlag = false;
@Override
protected void startConnection() {
System.out.println("A用户连接了数据库");
}
@Override
protected void endConnect() {
System.out.println("A用户释放了数据库");
}
protected boolean isBusy(){
return this.busyFlag;
}
protected void setBusyFlag(boolean isbusyFlag) {
this.busyFlag = isbusyFlag;
}
}
ConcreteUserB
public class ConcreteUserB extends AbstractClass{
private boolean busyFlag = false;
@Override
protected void startConnection() {
System.out.println("B用户连接了数据库");
}
@Override
protected void endConnect() {
System.out.println("B用户释放了数据库");
}
protected boolean isBusy(){
return this.busyFlag;
}
protected void setBusyFlag(boolean isbusyFlag) {
this.busyFlag = isbusyFlag;
}
}
5.3 修改测试的Client
public class Client {
public static void main(String[] args) {
// 创建一个具体用户A的模板对象
ConcreteUserA userA = new ConcreteUserA();
// 设置不忙
userA.setBusyFlag(false);
// 调用模板方法,完成连接和释放
userA.templateMethod();
ConcreteUserB userB = new ConcreteUserB();
// 设置忙
userB.setBusyFlag(true);
userB.templateMethod();
}
}
5.4 输出:
6. 总结
emmm,还是蛮好理解的,前面总结了,这就算了吧!!!去看LPL了