设计模式--模板方法设计模式

这里写目录标题


 场景:针对不同的度量模型来执行不同的方法,支持后面用最少的代码、最简单的方法来复用实现更多度量模型。

概念

在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法接口的情况下,重新定义算法中的某一些步骤。

举例

去银行处理业务步骤:1.取号、2.办业务、3.评价。三个步骤取号和评价都是固定的流程,但是每个人办理业务的不同需要不同的实现,我们就将办业务封装为一个抽象类:

/**
 * @Author CMLX
 * @Desc -> 模板方法设计模式的抽象类
 **/
public abstract class AbstractBusinessHandler {

    /**
     * 模板方法
     */
    public final void execute() {
        getNumber();
        handler();
        judge();
    }


    /**
     * 取号
     */
    private void getNumber() {
        Random random = new Random();
        System.out.println("rowNumber:" + random.nextInt());
    }

    /**
     * 办理
     */
    // 抽象的办理业务方法,由子类实现
    public abstract void handler();

    /**
     * 评价
     */
    private void judge() {
        System.out.println("give a judge");
    }

}

现在有人想办理业务就只需要继承这个抽象类重写handle方法,然后使用实现类对象调用execute方法就可以完成整个办理业务的流程。

/**
 * @Author CMLX
 * @Desc -> 存钱实现类
 **/
public class SaveMoneyHandler extends AbstractBusinessHandler{
    @Override
    public void handler() {
        System.out.println("save money $100");
    }

    public static void main(String[] args) {
        SaveMoneyHandler saveMoneyHandler = new SaveMoneyHandler();
        saveMoneyHandler.execute();
    }
}

模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

钩子方法

当模板方法中某一些步骤是可选的时候,也就是该步骤不一定执行,可以由子类来决定是否执行,这个时候就需要用上钩子。钩子是一种被声明在抽象类中的方法,但一般来说它只是空的或者具有默认值,子类可以实现覆盖该钩子,来设置算法步骤的某一步骤是否要执行。钩子可以让子类实现算法中可选的部分,让子类能够有机会对模板方法中某些一即将发生的步骤做出反应。
用银行办理业务的例子,买东西可以不用取号,那么代码实现如下:

/**
 * @Author CMLX
 * @Desc -> 模板方法设计模式的抽象类
 **/
public abstract class AbstractBusinessHandler {

    /**
     * 模板方法
     */
    public final void execute() {
        if (handler() == 1) {
            getNumber();
        }
        handler();
        judge();
    }

    /**
     * 是否是VIP
     * 通过处理业务不同来哦安定
     */
    public abstract int handler();

    /**
     * 取号
     */
    private void getNumber() {
        Random random = new Random();
        System.out.println("rowNumber:" + random.nextInt());
    }

    /**
     * 办理
     */
    // 抽象的办理业务方法,由子类实现
    public abstract void handler();

    /**
     * 评价
     */
    private void judge() {
        System.out.println("give a judge");
    }

}

实现类

/**
 * @Author CMLX
 * @Desc -> 存钱实现类
 **/
public class SaveMoneyHandler extends AbstractBusinessHandler{
    @Override
    public int handler() {
        return 1;
    }

    @Override
    public void handler() {
        System.out.println("save money $100");
    }

    public static void main(String[] args) {
        SaveMoneyHandler saveMoneyHandler = new SaveMoneyHandler();
        saveMoneyHandler.execute();
    }
}
/**
 * @Author CMLX
 * @Desc -> 购物实现类
 **/
public class ShoppingHandler extends AbstractBusinessHandler{
    @Override
    public int handler() {
        return 0;
    }

    @Override
    public void handler() {
        System.out.println("Shopping");
    }

    public static void main(String[] args) {
        ShoppingHandler shoppingHandler = new ShoppingHandler();
        shoppingHandler.execute();
    }
}

整合Spring

上面只是说明了整个实现原理,但是在开发过程中需要融入到Spring,根据入参不同怎么获取到不同实现类对象的实例,如下

/**
 * @Author CMLX
 * @Desc -> 将AbstractBusinessHandler实现类全部注入到Spring容器中
 **/
@Configuration
public class businessHandleConfig {
    
    // 实现类需要用@Component注入
    @Autowired
    List<AbstractBusinessHandler> businessHandlers;
    
    @Bean
    HashMap<Integer, AbstractBusinessHandler> businessHandleScript() {
        HashMap<Integer,AbstractBusinessHandler> map = new HashMap<>();
        for (AbstractBusinessHandler businessHandler : businessHandlers) {
            map.put(businessHandler.isVip(),businessHandler);
        }
        return map;
    }
    
}
/**
 * @Author CMLX
 * @Date -> 2021/5/12 12:20
 * @Desc -> 测试Controller
 **/
@RestController
public class TestBusinessHandleController {

    @Autowired
    HashMap<Integer,AbstractBusinessHandler> scrips;

    @RequestMapping("/test")
    public ModelAndView test(Integer type){
    	// 根据入参不同,通过type获取对应的实现类,完成相应的逻辑
        AbstractBusinessHandler abstractBusinessHandler = scrips.get(type);
        abstractBusinessHandler.execute();
        return null;
    }

}

测试结果
在这里插入图片描述
在这里插入图片描述
参考文章:https://www.hollischuang.com/archives/420

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值