代码改变世界

徒手撸设计模式-模板方法模式

2022-07-14 11:51  hikoukay  阅读(19)  评论(0编辑  收藏  举报

概念

https://www.runoob.com/design-pattern/template-pattern.html

模板方法设计模式是行为型设计模式中的一种,用在一个功能的完成需要经过一系列步骤,
这些步骤是固定的,但是中间某些步骤具体行为是待定的,在不同的场景中行为不同,
此时就可以考虑使用模板方法设计模式来完成,不同的场景对应不同的子类实现。

模板方法包含如下的角色:

抽象类/抽象模板(Abstract Class):负责给出一个算法的轮廓,由一个模板方法和若干个基本方法构成,
这些方法定义如下
    1:模板方法(该方法也正是模式的核心),定义算法的框架,按照某种顺序调用其中的基本方法。
    2:基本方法,可以包含如下的几种类型
        抽象方法:由具体的子类实现,作为定制行为,因为是抽象方法所以子类必须实现。
        具体方法:在抽象类中已经提供了具体的实现,子类可以继承或者重写(按照里氏替换原则,
        最好不要重写)。
        钩子方法:在抽象类中已经提供了实现(一般是空实现),类似于抽象方法,但是并非强制
        子类实现,因为已经提供了默认实现,可以在需要进行能力扩展时使用。
具体子类/具体实现(Concrete Class):必须实现抽象模板中的抽象方法,以及选择性的重载钩子方法。

定义一个模板接口

public interface Cookingtemplate {
    void buySth();
    void washFood();
    void cook();
    void eat();
    String make();
}

 

实现模板接口

@Slf4j
@Service
public class CookingFruitImpl implements Cookingtemplate {
    
    @Override
    public String make() {
        buySth();
        washFood();
        cook();
        eat();
        return "水果大餐";
    }
    @Override
    public void buySth() {
        log.info("买些苹果,芒果,香蕉,水蜜桃");
    }
    
    @Override
    public void washFood() {
        log.info("把水果洗干净");
    }
    
    @Override
    public void cook() {
        log.info("放点沙拉酱做水果沙拉");
    }
    
    @Override
    public void eat() {
        log.info("享用水果沙拉");
    }
}

 

@Slf4j
@Service
public class CookingVegetableImpl implements Cookingtemplate {

    @Override
    public String make() {
        buySth();
        washFood();
        cook();
        eat();
        return "蔬菜大餐";
    }
    @Override
    public void buySth() {
        log.info("买些菠菜,土豆,西红柿");
    }

    @Override
    public void washFood() {
        log.info("把蔬菜洗干净");
    }

    @Override
    public void cook() {
        log.info("做个西红柿炒土豆丝,炒个菠菜");
    }

    @Override
    public void eat() {
        log.info("享用小炒");
    }
}

 

定义枚举类将食物类型与烹饪模板实现类关联起来

/**
 * 做饭枚举
 */
public enum CookingEnum {
    /**
     * 蔬菜实现类枚举
     */
    VEGETABLE("vegetable","cookingVegetableImpl"),
    /**
     * 水果实现类枚举
     */
    FRUIT("fruit","cookingFruitImpl");

    private final String key;
    private final String value;
    CookingEnum(String key, String value) {
        this.key=key;
        this.value=value;
    }

    /**
     * 获取key
     * @return
     */
    public String getKey(){
        return key;
    }

    /**
     * 获取value
     * @return
     */
    public String getValue(){
        return value;
    }

}

 

控制器调用

/**
     * 模板方法设计模式+策略模式
     * 根据食物类型选择不同的工序出餐享用
     * @param foodType
     * @return
     */
    @GetMapping("/cook")
    public ResponseModel cook(String foodType)  {
        String serviceName="";
        if (CookingEnum.FRUIT.getKey().equals(foodType)){
            serviceName=CookingEnum.FRUIT.getValue();
        }else if (CookingEnum.VEGETABLE.getKey().equals(foodType)){
            serviceName=CookingEnum.VEGETABLE.getValue();
        }else {
            log.error("超标了,做不出来这种饭");
            return new ResponseModel("超标了,做不出来这种饭", 500, null);
        }
        Cookingtemplate bean = applicationContext.getBean(serviceName, Cookingtemplate.class);
        String make = bean.make();
        return new ResponseModel("做好了", 200, make);
    }

 

测试案例

 

 

2022-06-12 23:41:04.591  INFO 21536 --- [nio-8081-exec-6] c.k.s.d.t.impl.CookingVegetableImpl      : 买些菠菜,土豆,西红柿
2022-06-12 23:41:04.591  INFO 21536 --- [nio-8081-exec-6] c.k.s.d.t.impl.CookingVegetableImpl      : 把蔬菜洗干净
2022-06-12 23:41:04.591  INFO 21536 --- [nio-8081-exec-6] c.k.s.d.t.impl.CookingVegetableImpl      : 做个西红柿炒土豆丝,炒个菠菜
2022-06-12 23:41:04.591  INFO 21536 --- [nio-8081-exec-6] c.k.s.d.t.impl.CookingVegetableImpl      : 享用小炒

 

 

 

2022-06-12 23:42:13.353  INFO 21536 --- [nio-8081-exec-9] c.k.s.d.template.impl.CookingFruitImpl   : 买些苹果,芒果,香蕉,水蜜桃
2022-06-12 23:42:13.353  INFO 21536 --- [nio-8081-exec-9] c.k.s.d.template.impl.CookingFruitImpl   : 把水果洗干净
2022-06-12 23:42:13.353  INFO 21536 --- [nio-8081-exec-9] c.k.s.d.template.impl.CookingFruitImpl   : 放点沙拉酱做水果沙拉
2022-06-12 23:42:13.353  INFO 21536 --- [nio-8081-exec-9] c.k.s.d.template.impl.CookingFruitImpl   : 享用水果沙拉