模板方法模式

模板方法

定义(来自维基百科)

模板方法(Template Method)模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤。

特征和场景

  • 对复杂的算法进行分割,将算法中固定不变的部分设计为模板方法和父类具体方法,而一些可变的细节由其子类来实现。
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复

示例

C#示例

// 计算薪资抽象基类
public abstrace class Salary
{
    // 计算奖金
    public double Calc()
    {
        return Attendance() + Performance();
    }

    // 考勤
    public abstract double Attendance();

    // 绩效
    public abstract double Performance();
}

// 网络部薪资
public class NetDepartmentSalary: Salary
{
    public override double Attendance()
    {
        return 0;
    }

    public override double Performance()
    {
        return 0;
    }
}

// 人力资源部薪资
public class EmployeeResourceSalary: Salary
{
    public override double Attendance()
    {
        return 0;
    }

    public override double Performance()
    {
        return 0;
    }    
}

// 消费场景
public class MainApp
{
    public static void Main()
    {
        Salary netSalary = new NetDepartmentSalary();
        var netSalaryPay = netSalary.Calc();

        Salary empResSalary = new EmployeeResourceSalary();
        var empSalaryPay = empResSalary.Calc();
    }
}

思考:如何改进本示例以计算各部门不同员工的应得薪资?

Vuejs示例

<template>
    <div>
        <el-row>
            <top-bar></top-bar>
        </el-row>
        <el-row>
            <el-col :span="4">
                <body-left></body-left>
            </el-col>
            <el-col :span="20">
                <router-view></router-view>
            </el-col>
        </el-row>
    </div>
</template>

<script>
    import topBar from '@/components/topbar.vue'
    import bodyLeft from '@/components/bodyLeft.vue'

    export default {
        data() {
            return {
            }
        },
        components: {
            topBar, bodyLeft
        },
        methods: {
            getToken() {
                return document.cookie.valueOf('token').substr(6, 32)
            },
            checkToken(token, func) {
                this.$axios.get(this.$api.API_LOGIN + '/' + token).then(res => {
                    if (res.status === 200 && res.data.status === 'true') {
                        func()
                    }
                }).catch(e => {
                    console.log(e)
                })
            }
        },
        mounted() {
            let token = this.getToken()
            if (token === 'undefined') {
                this.$router.push('/login')
            }
            this.checkToken(token, () => {
                this.$router.push('/home')
            })
        }
    }
</script>

Vuejs示例中,组件top-bar, body-left, 以及 router-view, 都可以看作是模板方法的子类实现,该示例本身的html则相当于C#示例中的抽象基类。

优点

  1. 在父类中形式化的定义一个算法,由它的子类实现细节的处理,在子类实现详细的业务逻辑时不会改变算法中步骤的执行次序;
  2. 是一种基于继承的代码复用技术,提取类库中的公共行为并将其放在父类中,通过子类实现不同的行为,鼓励开发人员使用继承来实现代码复用。

缺点

  1. 需要为每个基本方法的不同实现提供一个子类的实现,如果父类中可变的基本方法太多,将会导致类的个数增加,系统越来越庞大,设计也更加抽象化,此时,可结合桥接模式来进行设计。

练习

编写示例,实现不同部门间工资的计算

总结

模板方法模式是一种简单常用的模式,我们在进行开发的时候,会经常有意无意地使用它,一般来说,该模式不会单独使用,跟其他模式混用的情况比较多,如工厂,策略模式等。

思考题链接

改进版的应得薪资计算方法

本文完。

posted @ 2017-08-21 18:47  DebugLife  阅读(203)  评论(0编辑  收藏  举报