一、引言:
模板方法模式非常简单,每个人在java代码编写中都会用到,其方针图如下:
实际上,模板方法模式核心就是java的继承机制,父类叫做抽象模板,里面的方法分为两类:一类是基本方法,就是需要子类具体实现的方法,这类方法如果不需要过多的暴露接口,通常使用protected关键字声明,另一类就是模板方法,这类都是具体实现方法,完成固定逻辑,由父类完成,通常,在前面会加上关键字final,防止覆写。
二、 测试demo:
package com.example.javatestlib;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/* 模板为抽象类 */
abstract class HummerModel {
/*
* 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正
* 是要能够发动起来,那这个实现要在实现类里了,需要子类实现的方法全部为protected
*/
protected abstract void start();
protected abstract void stop();
protected abstract void alarm();
protected abstract void engineBoom();
/* 公共方法为final */
final public void run() {
this.start();
this.engineBoom();
if(this.isAlarm()){
this.alarm();
}
this.stop();
}
/* 钩子方法,默认喇叭是会响的 */
protected boolean isAlarm(){
return true;
}
}
/* 子类一:覆写父类中的抽象方法 */
class HummerH1Model extends HummerModel {
private boolean alarmFlag = true;
protected void alarm() {
System.out.println("悍马H1鸣笛...");
}
protected void engineBoom() {
System.out.println("悍马H1引擎声音是这样的...");
}
protected void start() {
System.out.println("悍马H1发动...");
}
protected void stop() {
System.out.println("悍马H1停车...");
}
protected boolean isAlarm() {
return this.alarmFlag;
}
/* 要不要响喇叭,是由客户来决定的 */
public void setAlarm(boolean isAlarm) {
this.alarmFlag = isAlarm;
}
}
/* 子类二:覆写父类中的抽象方法 */
class HummerH2Model extends HummerModel {
protected void alarm() {
System.out.println("悍马H2鸣笛...");
}
protected void engineBoom() {
System.out.println("悍马H2引擎声音是这样的...");
}
protected void start() {
System.out.println("悍马H2发动...");
}
protected void stop() {
System.out.println("悍马H2停车...");
}
/* 默认没有喇叭的 */
protected boolean isAlarm() {
return false;
}
}
public class ModelDesign {
public static void main(String[] args) throws IOException {
System.out.println("-------H1型号悍马--------");
System.out.println("H1型号的悍马是否需要喇叭声响?0-不需要 1-需要");
String type=(new BufferedReader(new InputStreamReader(System.in))).readLine();
HummerH1Model h1 = new HummerH1Model();
if(type.equals("0")){
h1.setAlarm(false);
}
h1.run();
System.out.println("\n-------H2型号悍马--------");
HummerH2Model h2 = new HummerH2Model();
h2.run();
}
}
三、建造者模式:
建造者模式方针图如下:
在上面的模板方法模式demo中,我们看到每一个最终的产品对象都是固定工艺顺序的,在实际生活中,需求会随时变更,那么,零件装配的不同执行顺序可能会产生不同的结果,在这种场景下,就需要使用到建造者模式了,这种模式跟模板方法的最大区别在与会创建一个建造者的抽象类,继承自该类的实现类会去实现具体的工艺顺序,为了更好的实现封装,避免上层知道下面的实现细节,通常会创建一个导演类director用于管理建造者。
建造者模式跟工厂模式有些相似,建造者模式关注的是零件类型和装配工艺(顺序),这是它与工厂方法模式最大不同的地方,建造者模式最主要的功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了, 通俗地说就是零件的装配,顺序不同产生的对象也不同;而工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是它关心的。
四、建造者demo:
package com.example.javatestlib;
import java.util.ArrayList;
/* 产品抽象类 */
abstract class CarModel {
/* 这个参数是各个基本方法执行的顺序 */
private ArrayList<String> sequence = new ArrayList<String>();
protected abstract void start();
protected abstract void stop();
protected abstract void alarm();
protected abstract void engineBoom();
final public void run() {
for(int i = 0; i < this.sequence.size(); i++){
String actionName = this.sequence.get(i);
if(actionName.equalsIgnoreCase("start")){
this.start();
}else if(actionName.equalsIgnoreCase("stop")){
this.stop();
}else if(actionName.equalsIgnoreCase("alarm")){
this.alarm();
}else if(actionName.equalsIgnoreCase("engine boom")){
this.engineBoom();
}
}
}
final public void setSequence(ArrayList sequence){
this.sequence = sequence;
}
}
/* 具体产品一:奔驰车 */
class BenzModel extends CarModel {
protected void alarm() {
System.out.println("奔驰车的喇叭声音是这个样子的...");
}
protected void engineBoom() {
System.out.println("奔驰车的引擎是这个声音的...");
}
protected void start() {
System.out.println("奔驰车跑起来是这个样子的...");
}
protected void stop() {
System.out.println("奔驰车应该这样停车...");
}
}
/* 具体产品一:宝马车 */
class BMWModel extends CarModel {
protected void alarm() {
System.out.println("宝马车的喇叭声音是这个样子的...");
}
protected void engineBoom() {
System.out.println("宝马车的引擎是这个声音的...");
}
protected void start() {
System.out.println("宝马车跑起来是这个样子的...");
}
protected void stop() {
System.out.println("宝马车应该这样停车...");
}
}
/* 建造者抽象类 */
abstract class CarBuilder {
/* 建造一个模型, 你要给我一个顺序要求, 就是组装顺序 */
public abstract void setSequence(ArrayList<String> sequence);
/* 设置完毕顺序后, 就可以直接拿到这个车辆模型 */
public abstract CarModel getCarModel();
}
/* 建造者具体类:奔驰车 */
class BenzBuilder extends CarBuilder {
private BenzModel benz = new BenzModel();
public CarModel getCarModel() {
return this.benz;
}
public void setSequence(ArrayList<String> sequence) {
this.benz.setSequence(sequence);
}
}
/* 建造者具体类:宝马车 */
class BMWBuilder extends CarBuilder {
private BMWModel bmw = new BMWModel();
public CarModel getCarModel() {
return this.bmw;
}
public void setSequence(ArrayList<String> sequence) {
this.bmw.setSequence(sequence);
}
}
/* 导演类用于封装 */
class Director {
private ArrayList<String> sequence = new ArrayList();
private BenzBuilder benzBuilder = new BenzBuilder();
private BMWBuilder bmwBuilder = new BMWBuilder();
/**
* A类型的奔驰车模型, 先start, 然后stop, 其他什么引擎、 喇叭一概没有
*/
public BenzModel getABenzModel(){
this.sequence.clear();
this.sequence.add("start");
this.sequence.add("stop");
this.benzBuilder.setSequence(this.sequence);
return (BenzModel)this.benzBuilder.getCarModel();
}
/**
B型号的奔驰车模型, 是先发动引擎, 然后启动, 然后停止, 没有喇叭
*/
public BenzModel getBBenzModel(){
this.sequence.clear();
this.sequence.add("engine boom");
this.sequence.add("start");
this.sequence.add("stop");this.benzBuilder.setSequence(this.sequence);
return (BenzModel)this.benzBuilder.getCarModel();
}
/**
C型号的宝马车是先按下喇叭(炫耀嘛) , 然后启动, 然后停止
*/
public BMWModel getCBMWModel(){
this.sequence.clear();
this.sequence.add("alarm");
this.sequence.add("start");
this.sequence.add("stop");
this.bmwBuilder.setSequence(this.sequence);
return (BMWModel)this.bmwBuilder.getCarModel();
}
/**
D类型的宝马车只有一个功能, 就是跑, 启动起来就跑, 永远不停止
*/
public BMWModel getDBMWModel(){
this.sequence.clear();
this.sequence.add("start");
this.bmwBuilder.setSequence(this.sequence);
return (BMWModel)this.benzBuilder.getCarModel();
}
}
public class BuilderDesign {
public static void main(String[] args) {
/* 直接创建导演类来控制建造者 */
Director director = new Director();
for(int i = 0; i < 2; i++){
director.getABenzModel().run();
}
for(int i = 0; i < 3; i++){
director.getBBenzModel().run();
}
for(int i = 0; i < 2; i++){
director.getCBMWModel().run();
}
}
}
博客参考书籍:秦小波 《设计模式之禅(第2版)》