将具体处理交给子类
1.基本介绍
父类定义处理流程的框架,在子类实现中具体处理
模板方法设计模式是指带有模板功能的模式,组成模板的方法被定义在父类中。这些方法都是抽象方法,所以只查看父类的代码无法知道这些方法最终会进行如何的具体处理。只能知道父类是如何去调用这些方法
实现以上抽象方法的就是子类.子类中实现了抽象方法也就是决定了具体的处理。也就是说,只要不同的子类实现不同的具体处理,当父类中的模板方法被调用时程序行为也不同,但是不管子类中的具体实现如何,处理流程都会按照父类中所定义的那样执行。
2.实现过程
类的一览图:
程序类图:
AbstractDisplay
其中规定了抽象方法以及其处理流程。
/**
* @author Jay
* @date 2019/5/22 21:54
* @description 父类为抽象类, 规定抽象方法以及业务处理流程
*/
public abstract class AbstractDisplay {
/**
* 抽象方法
*/
public abstract void open();
public abstract void print();
public abstract void close();
/**
* 抽象类中允许非抽象方法,规定业务处理流程,同时
* 该方法用final修饰,子类无法重写,故只能按照其父类规定来执行
*/
public final void display() {
open();
for (int i = 0; i < 5; i++) {
print();
}
close();
}
}
CharDisplay
一个实现子类,具体实现父类中的抽象方法。
/**
* @author Jay
* @date 2019/5/22 22:09
* @description
*/
public class CharDisplay extends AbstractDisplay {
private char ch;
public CharDisplay(char ch) {
super();
this.ch = ch;
}
@Override
public void open() {
System.out.print("<<");
}
@Override
public void print() {
System.out.print(ch);
}
@Override
public void close() {
System.out.print(">>");
}
}
StringDisplay
另一个实现子类,实现父类中抽象方法。
/**
* @author Jay
* @date 2019/5/22 22:13
* @description
*/
public class StringDisplay extends AbstractDisplay {
private String ch;
public StringDisplay(String ch) {
this.ch = ch;
}
@Override
public void open() {
System.out.println("**");
}
@Override
public void print() {
System.out.println(ch);
}
@Override
public void close() {
System.out.println("**");
}
}
Main
/**
* @author Jay
* @date 2019/5/22 22:14
* @description
*/
public class Main {
public static void main(String[] args) {
//父类引用指向子类实现类对象.
//可以直接调用父类方法,不需要进行类型判断,里氏替换原则(LSP)
AbstractDisplay d1 = new CharDisplay('A');
AbstractDisplay d2 = new StringDisplay("Hello World");
d1.display();
System.out.println("\n==========================");
d2.display();
}
}
<<AAAAA>> //CharDisplay
==========================
**
Hello World //StringDisplay
Hello World
Hello World
Hello World //不同的子类具体实现的抽象方法也不同,根据具体需求来定义.
Hello World
**
3. 设计模式中的主要角色
-
AbstractClass(抽象类)
抽象类不仅仅负责实施模板的方法,还负责声明模板方法中所使用到的抽象方法,这些抽象方法在子类中具体实现。
-
ConcreteClass(具体类)
具体实现父类中所定义的抽象方法,这里所实现的方法将会在父类的模板方法中被调用,实现具体业务。
4.使用优点
-
使逻辑处理通用化
具体的算法处理在父类中进行,子类只负责抽象方法的具体实现,不需要在子类中进行算法编写,若需求改动,只需改动父类模板中的算法,无需改动具体子类的每一个算法,从而提高的代码的可维护性.
-
子父类的协作
子类和父类是紧密联系共同工作的,子类中实现父类中声明的抽象方法时,必须理解这些抽象方法被调用的时机,在看不到父类源码的情况下,想要编写出子类是非常空难的。
-
父类和子类的一致性
使用父类类型的变量接收子类实例化对象的引用,在调用父类中特有的算法时不需要进行类型的判断。无论在父类类型的变量中保存个子类的实例,都可以运行,称为LSP(里氏替换原则)。
5.类的层次与抽象类
5.1 父类对子类的要求
我们在理解类的层次时,经常是从子类角度思考的。
- 在子类中可以使用父类定义的方法.
- 可以在子类中增加新的方法以实现新的功能.
- 在子类中重写父类方法可以改变程序的行为.
在父类的角度考虑:
- 期待子类去实现抽象方法.
- 要求子类实现抽象方法.
子类责任: 子类具有实现在父类中所声明的抽象方法的责任.
5.2 抽象类的意义
抽象类无法生成实例,可以决定抽象方法的名称,交给具体的子类实现,同时可以在抽象类中确定处理的流程。
5.3 子类和父类的协作
将更多的方法放在父类中实现可以让子类变的轻松,但是同时也会降低子类的灵活性,反之,若是父类中实现的方法过少,子类会过于臃肿,会导致子类之间出现的代码重复,增加代码的难度,所以父类和子类中方法的定义很重要。