代碼變形記之模板方法模式
背景
有5類數(shù)據(jù)A、B、C、D、E,需要分別進(jìn)行處理。
優(yōu)化前
通過ParamBuilder來分別構(gòu)造各自參數(shù),然后在Runner中分別調(diào)用,分別判斷。
package TemplateMethodPattern.before;
public class Runner {
public static void main(String[] args) {
Param param = new Param();
ParamBuilder paramBuilder = new ParamBuilder();
// 處理數(shù)據(jù)A
boolean result = paramBuilder.buildA(param);
if (!result) {
return;
}
boolean inserted = doIt(param);
if (!inserted) {
return;
}
// 處理數(shù)據(jù)B
result = paramBuilder.buildB(param);
if (!result) {
return;
}
inserted = doIt(param);
if (!inserted) {
return;
}
// 處理數(shù)據(jù)C
result = paramBuilder.buildC(param);
if (!result) {
return;
}
inserted = doIt(param);
if (!inserted) {
return;
}
// 處理數(shù)據(jù)D
result = paramBuilder.buildD(param);
if (!result) {
return;
}
inserted = doIt(param);
if (!inserted) {
return;
}
// 處理數(shù)據(jù)E
result = paramBuilder.buildE(param);
if (!result) {
return;
}
inserted = doIt(param);
if (!inserted) {
return;
}
}
public static boolean doIt(Param param) {
return param.flag;
}
}
package TemplateMethodPattern.before;
import lombok.Data;
@Data
public class Param {
public boolean flag;
}
package TemplateMethodPattern.before;
public class ParamBuilder {
public boolean buildA(Param param) {
return true;
}
public boolean buildB(Param param) {
return false;
}
public boolean buildC(Param param) {
return true;
}
public boolean buildD(Param param) {
return false;
}
public boolean buildE(Param param) {
return true;
}
}
存在問題
Runner中存在較多重復(fù)代碼。
優(yōu)化方法
模板方法模式,Template Method Pattern。將重復(fù)代碼抽象為一個(gè)抽象類,定義多個(gè)子類繼承并實(shí)現(xiàn)各自代碼。
優(yōu)化后
AbstractHandler抽象了重復(fù)方法,子類繼承后實(shí)現(xiàn)build()方法。Runner中調(diào)用process()方法來遍歷子類對(duì)象進(jìn)行處理。
package TemplateMethodPattern.after;
import TemplateMethodPattern.after.handler.*;
import TemplateMethodPattern.before.Param;
import java.util.Arrays;
import java.util.List;
public class Runner {
public static void main(String[] args) {
Param param = new Param();
List<AbstractHandler> handlers = Arrays.asList(
new AHandler(),
new BHandler(),
new CHandler(),
new DHandler(),
new EHandler()
);
for (AbstractHandler handler : handlers) {
if (!handler.process(param, Runner::doIt)) {
return;
}
}
}
public static boolean doIt(Param param) {
return param.flag;
}
}
package TemplateMethodPattern.after.handler;
import TemplateMethodPattern.before.Param;
import java.util.function.Function;
public abstract class AbstractHandler {
protected abstract boolean build(Param param);
public boolean process(Param param, Function<Param, Boolean> doIt) {
boolean result = build(param);
if (!result) {
return false;
}
return doIt.apply(param);
}
}
package TemplateMethodPattern.after.handler;
import TemplateMethodPattern.before.Param;
public class AHandler extends AbstractHandler{
@Override
protected boolean build(Param param) {
return true;
}
}
package TemplateMethodPattern.after.handler;
import TemplateMethodPattern.before.Param;
public class BHandler extends AbstractHandler{
@Override
protected boolean build(Param param) {
return false;
}
}
package TemplateMethodPattern.after.handler;
import TemplateMethodPattern.before.Param;
public class CHandler extends AbstractHandler{
@Override
protected boolean build(Param param) {
return true;
}
}
package TemplateMethodPattern.after.handler;
import TemplateMethodPattern.before.Param;
public class DHandler extends AbstractHandler{
@Override
protected boolean build(Param param) {
return false;
}
}
package TemplateMethodPattern.after.handler;
import TemplateMethodPattern.before.Param;
public class EHandler extends AbstractHandler{
@Override
protected boolean build(Param param) {
return true;
}
}
個(gè)人感想,因?yàn)槲沂菑腜ython轉(zhuǎn)到Java,在使用設(shè)計(jì)模式解決這個(gè)問題后,我也思考了如果使用Python該怎么處理?Python是動(dòng)態(tài)語言,有鴨子類型,對(duì)于重復(fù)代碼通過定義一個(gè)公共函數(shù),動(dòng)態(tài)綁定類型就能解決,感興趣的同學(xué)可以試試。不同的語言都各自的優(yōu)勢,也有各自的限制。也有各自的解決方法。