三、设计模式
5.模板模式(Template Method Pattern)
5.1 定义
定义抽象类并且声明一些抽象基本方法供子类实现不同逻辑,同时在抽象类中定义具体方法把抽象基本方法封装起来,这就是模板方法模式。
5.2 结构图
5.3 角色
①. 抽象模板(Abstract Template):
- 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
- 定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
②. 具体模板(Concrete Template):
- 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
- 每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
5.4 方法
①. 模板方法
- 一个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。
- 一个抽象类可以有任意多个模板方法,而不限于一个。每一个模板方法都可以调用任意多个具体方法。
②. 基本方法
- 抽象方法: 一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。
- 具体方法: 一个具体方法由抽象类声明并实现,而子类并不实现或置换。
- 钩子方法: 一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。
5.5 代码实现
模板角色
public abstract class AbstractClass {
protected boolean isNeedUnlock = true;
/**
* 抽象方法
*/
protected abstract void unlock();
/**
* 抽象方法
*/
protected abstract void ride();
/**
* 钩子方法
* [@param](https://my.oschina.net/u/2303379) isNeedUnlock
*/
protected void isNeedUnlock(boolean isNeedUnlock) {
this.isNeedUnlock = isNeedUnlock;
}
/**
* 模板方法
*/
public final void use() {
if (isNeedUnlock) {
unlock();
} else {
System.out.println("========锁坏了,不用解锁========");
}
ride();
}
}
模板实现
public class ScanBicycle extends AbstractClass {
[@Override](https://my.oschina.net/u/1162528)
protected void unlock() {
System.out.println("========" + "扫码开锁" + "========");
}
[@Override](https://my.oschina.net/u/1162528)
protected void ride() {
System.out.println(getClass().getSimpleName() + "骑起来很拉风");
}
protected void isNeedUnlock(boolean isNeedUnlock) {
this.isNeedUnlock = isNeedUnlock;
}
}
模板实现
public class CodeBicycle extends AbstractClass {
[@Override](https://my.oschina.net/u/1162528)
protected void unlock() {
System.out.println("========" + "密码开锁" + "========");
}
[@Override](https://my.oschina.net/u/1162528)
protected void ride() {
System.out.println(getClass().getSimpleName() + "骑起来很拉风");
}
protected void isNeedUnlock(boolean isNeedUnlock) {
this.isNeedUnlock = isNeedUnlock;
}
}
测试
class AbstractClassTest {
@Test
void test() {
ScanBicycle scanBicycle = new ScanBicycle();
scanBicycle.isNeedUnlock(false);
scanBicycle.use();
CodeBicycle codeBicycle = new CodeBicycle();
codeBicycle.isNeedUnlock(true);
codeBicycle.use();
}
@Test
void test1() {
ScanBicycle scanBicycle = new ScanBicycle();
scanBicycle.use();
CodeBicycle codeBicycle = new CodeBicycle();
codeBicycle.use();
}
}
控制台输出
5.6 优点
-
良好的封装性。把公有的不变的方法封装在父类,而子类负责实现具体逻辑。
-
良好的扩展性:增加功能由子类实现基本方法扩展,符合单一职责原则和开闭原则。
-
复用代码。
5.7 缺点
-
由于是通过继承实现代码复用来改变算法,灵活度会降低。
-
子类的执行影响父类的结果,增加代码阅读难度。