谈笑间学会模板方法模式

1 背景

某天早上,Skr郎正在一边悠哉的吃着加了三跟烤肠的手抓饼,一边悠闲地逛着论坛,看着沙雕网友的帖子,Skr郎会心一笑,正欲给沙雕帖子点赞,邮件忽的弹出,Skr郎慢悠悠的打开邮件

            公司关于XXXX年XX月XX日生产事故通报批评
    在XXXX年XX月XX日版本上线后,由于GP6(软件工程师)与TP9(测试工程师)的个人原因,导致上线功能出现异常,客户投诉,对此予以通报批评!

    扣除XX月绩效........
    .......
    .......
                                        XXXX年XX月XX日      

Skr郎看着旁边的脸色很差GP6问道:什么生产事故?怎么都通报了?

GP6: 哎,原有的导出文件,统一修改表头与表尾的内容格式,需要改动的地方太多了,有几个处漏改了,你也看一下,前世之事,后事之师啊!

Skr: 好的,我要吸取这次教训,避免以后出现同样的错误!

2 事故代码

/**
 * 交易Service
 *
 * @author gp6
 * @date 2020/3/20
 */
public class TradeService {

    /**
     * 交易表单导出
     *
     * @param storeName 店铺名称
     */
    public void exportTradeData(String storeName) {
        System.out.println("表头:Skr-" + storeName);
        System.out.println("交易数据");
        System.out.println("表尾:当天日期");
    }
}

----------------------------------------------------------------------------------------------------

/**
* 订单Service
*
* @author gp6
* @date 2020/3/20
*/
public class OrderService {

    /**
     * 订单表单导出
     *
     * @param storeName 店铺名称
     */
    public  void exportOrderData(String storeName) {
        System.out.println("表头:Skr-" + storeName);
        System.out.println("订单数据");
        System.out.println("表尾:当天日期");
    }
}

----------------------------------------------------------------------------------------------------

/**
 * 粉丝Service
 *
 * @author gp6
 * @date 2020/3/20
 */
public class FansService {

    /**
     * 新增粉丝表单导出
     *
     * @param storeName 店铺名称
     */
    public void exportAddFansData(String storeName) {
        System.out.println("表头:Skr-" + storeName);
        System.out.println("新增粉丝数据");
        System.out.println("表尾:当天日期");
    }
}

----------------------------------------------------------------------------------------------------

/**
 * 测试模板方法
 *
 * @author gp6
 * @date 2020/3/20
 */
public class TestTemplate {

    public static void main(String[] args) {
        // 1 : 交易表单导出
        TradeService tradeService = new TradeService();
        tradeService.exportTradeData("SM旗舰店");

        // 2 : 订单表单导出
        OrderService orderService = new OrderService();
        orderService.exportOrderData("SM旗舰店");

         // 3 : 新增粉丝表单导出
        FansService fansService = new FansService();
        fansService.exportAddFansData("SM旗舰店");

        // 4 : 等等等等很多个
    }
}

GP6: 本次的需求就是将每个导出文件表头与表尾的内容格式进行统一修改,结果我有几个地方的导出漏掉了,因为需求简单,测试只对其中几个进行测试,没有问题,他就没有进行全部测试…

Skr郎看着代码,说道: 还好这次没有涉及到金钱损失,要是你这次改动的是涉及金钱交易的逻辑,你估计就要直接卷铺盖滚蛋…

GP6: 哎,你就别调侃我了,你说这么多地方,我哪能找全啊,

Skr: 既然他们表头表尾都是一样的你为什么不把通用的逻辑抽取出来?这样的话,下次如果再修改表头与表尾的内容格式,是不是只需改动抽取出来的公用逻辑就行!

GP6: 有道理哦!那我把通用逻辑抽到一个工具类吧

Skr: 敲代码之前要先想一想"高内聚,低耦合",通用逻辑抽取,用模板方法模式不是更符合"高内聚"吗

3 模板方法模式

定义:
	定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤

看了模板方法模式的定义,是不是很符合这种场景

定义一个操作中的算法骨架(表头,获取XX数据,表尾),而将算法的一些步骤(获取XX数据)延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤(获取的数据不同)

简直完美,Skr郎沾沾自喜

/**
 * 模板方法的核心(定义一个操作中的算法骨架)
 *
 * @author gp6
 * @date 2020/3/20
 */
public abstract class AbstractTemplate {

    /**
     * 导出数据
     *
     * @param storeName 店铺名称
     */
    public void exportData(String storeName) {
        // 通用逻辑--表头
        header(storeName);

        // 获取不同的数据
        getData();

        // 通用逻辑--表尾
        end();
    }

    /**
     * 表头
     *
     * @param storeName 店铺名称
     */
    private void header(String storeName) {
        System.out.println("表头:Skr-" + storeName);
    }

    /**
     * 表尾
     */
    private void end() {
        System.out.println("当天日期");
    }

    /**
     * 获取数据(算法的一些步骤(获取XX数据)延迟到子类)
     */
    public abstract void getData();
}


/**
 * 交易Service
 *
 * @author gp6
 * @date 2020/3/20
 */
public class TradeService extends AbstractTemplate{

    /**
     * 获取交易数据
     */
    @Override
    public void getData() {
        System.out.println("交易数据");
    }
}

/**
* 订单Service
*
* @author gp6
* @date 2020/3/20
*/
public class OrderService  extends AbstractTemplate{

    /**
     * 获取订单数据
     */
    @Override
    public void getData() {
        System.out.println("订单数据");
    }
}

/**
 * 粉丝Service
 *
 * @author gp6
 * @date 2020/3/20
 */
public class FansService extends AbstractTemplate{

    /**
     * 获取新增粉丝数据
     */
    @Override
    public void getData() {
        System.out.println("新增粉丝数据");
    }
}

/**
 * 测试模板方法
 *
 * @author gp6
 * @date 2020/3/20
 */
public class TestTemplate {

    public static void main(String[] args) {
        // 1 : 交易表单导出
        TradeService tradeService = new TradeService();
        tradeService.exportData("SM旗舰店");

        // 2 : 订单表单导出
        OrderService orderService = new OrderService();
        orderService.exportData("SM旗舰店");

        // 3 : 新增粉丝表单导出
        FansService fansService = new FansService();
        fansService.exportData("SM旗舰店");
    }
}

此时如果要修改表头或表尾内容格式,只需在AbstractTemplate此类中修改即可

Skr郎写到此处,心满意足的点点头,心中评价道:这段代码,逻辑严谨,注释清晰,优雅中透露着洒脱,洒脱中透露着不羁,真是"此码只应天上有,人间难得几回寻!"
呀! 想不到我作诗的功夫也如此深厚,哎,如此完美的男人,别人只能羡慕嫉妒恨!

4 模板方法模式类图

模板方法模式类图

类图中Man/Woman相当于文章中的OrderService/FansService/TradeService

allShop()相当于文章中的exportData()

go()相当于文章中的header()/end()

shop()相当于文章中的exportData()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值