java设计模式--模板方法

模板方法  Template

整体算法的设计是一个抽象类, 它有一系列抽象方法, 代表算法中可被定制的步骤, 同时这个类中包含了一些通用代码。 算法的每一个变种由具体的类实现, 它们重写了抽象方法, 提供了相应的实现。

模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。

示例:

假设有一个检查流程,要检查身份信息,信用信息,收入情况。这些信息来源不同,如检查公司和个人的信息情况,那么对于不同的来源信息,检查方法不同,但是检查流程是统一的,如定义个流程(或者是优先级) 检查身份信息-->信用信息-->收入情况。 

代码实现:

public class TemplateTest{

    /**
     * 检查使用的模板
     */
    static abstract class CheckTemplate {
        //检查身份信息
        protected abstract void identity();
        //检查信用信息
        protected abstract void creditHistory();
        //检查收入信息
        protected abstract void incomeHistory();

        //检查流程定义
        public void check(){
            this.identity();
            this.creditHistory();
            this.incomeHistory();
        }
    }

    /**
     * 检查模式的基类,提供默认的实现
     */
    static class CheckTemplateBase extends CheckTemplate{
        @Override
        protected void identity() {
            System.out.println("basecheck identity");
        }

        @Override
        protected void creditHistory() {
            System.out.println("basecheck creditHistory");
        }

        @Override
        protected void incomeHistory() {
            System.out.println("basecheck incomeHistory");
        }
    }

    static class CheckCompany extends CheckTemplateBase{
        @Override
        protected void incomeHistory() {
            System.out.println("check company");
        }
    }

    //测试
    public static void main(String[] args) {
        CheckCompany checkCompany = new CheckCompany();
        checkCompany.check();
    }
    
}

说明:
1、定义一个检查模板CheckTemplate ,模板中定义了 protected 的抽象检查方法,主要是不对外提供调用。check() 方法提供是的检查流程。
2、声明检查模板接着声明检查的基类 CheckTemplateBase ,主要为了提供一个默认的实现,所有的检查类可以继承这个基类。
3、最后就是具体的要检查的类型 CheckCompany 继承 CheckTemplateBase 类,可以实现具体的检查方式。

java8 函数jdk8 函数式编程实现,使用“函数接口”

代码:

public class TemplateTest{

    /**
     * 函数接口
     */
    interface Criteria{
        void check();
    }

    /**
     * 模板
     */
    static class CheckTemplate {
        //函数接口 作为属性
        private final Criteria identity;
        private final Criteria creditHistory;
        private final Criteria incomeHistory;

        public CheckTemplate(Criteria identity,
                             Criteria creditHistory,
                             Criteria incomeHistory) {
            this.identity = identity;
            this.creditHistory = creditHistory;
            this.incomeHistory = incomeHistory;
        }

        //模板方法
        public void checkLoanApplication(){
            identity.check();
            creditHistory.check();
            incomeHistory.check();
        }
    }


    /**
     * 默认的检查类,每一个方法,都对应一个 函数接口
     * 所有的处理子类实现可以继承此类
     */
    static class CheckBase {
        public void identity() {
            System.out.println("basecheck identity");
        }
        public void creditHistory() {
            System.out.println("basecheck creditHistory");
        }
        public void incomeHistory() {
            System.out.println("basecheck incomeHistory");
        }
    }

    /**
     * 检查
     */
    static class Check extends CheckTemplate {
        public Check(CheckBase check) {
            //传入都是函数接口
            super(check::identity,
                    check::creditHistory,
                    check::incomeHistory);
        }
    }

    /**
     * Company 处理流程
     *
     */
    static class CompanyCheck extends CheckBase {
        //重写  creditHistory 方法
        public void creditHistory(){
            System.out.println("company creditHistory ");
        }
    }


    public static void main(String[] args) {
        Check c = new Check(new CompanyCheck());
        c.checkLoanApplication();
    }

}
说明:
1、首先声明一个函数式接口 Criteria,定义了一个检查方法 check()
2、声明检查模板 CheckTemplate,在模板是声明了Criteria 属性,用来作为检查流程的定义,每一个Criteria 属性对应一个检查流程的一个环节。

3、检查的基类 CheckBase 主要为了提供一个默认的实现,所有的检查类可以继承这个基类。

 4、声明具体检查 CompanyCheck extends CheckBase,可以自定义检查的内容,如果不定义就使用默认的。

5、声明检查类 Check extends CheckTemplate ,声明了一个构造方法参数是检查基类(接口也可以) CheckBase。有两个作用:a:用于所有的具休检查类的基类,b:Check 构造方法的参数,只要是CheckBase 子类就可以构造Check ,代码清晰规范。在构造方法中,直接调用父类的构造方法,参数就是“函数接口”。

java8终极代码:

public class TemplateTest{

    /**
     * 函数接口
     */
    interface Criteria{
        void check();
    }

    /**
     * 模板
     */
    static class CheckTemplate {
        //函数接口 作为属性
        private final Criteria identity;
        private final Criteria creditHistory;
        private final Criteria incomeHistory;

        public CheckTemplate(Criteria identity,
                             Criteria creditHistory,
                             Criteria incomeHistory) {
            this.identity = identity;
            this.creditHistory = creditHistory;
            this.incomeHistory = incomeHistory;
        }

        //模板方法
        public void checkLoanApplication(){
            identity.check();
            creditHistory.check();
            incomeHistory.check();
        }
    }

    /**
     * 默认的检查类,每一个方法,都对应一个 函数接口
     * 所有的处理子类实现可以继承此类
     */
    static class CheckBase {
        public void companyIdentity() {
            System.out.println("company identity");
        }
        public void companyCreditHistory() {
            System.out.println("company creditHistory");
        }
        public void companyIncomeHistory() {
            System.out.println("company incomeHistory");
        }
        //大公司的收入检查
        public void bigCompanyIncomeHistory() {
            System.out.println("big company incomeHistory");
        }

    }

    public static void main(String[] args) {
        CheckBase checkBase = new CheckBase();
        CheckTemplate checkTemplate =  new CheckTemplate(checkBase::companyIdentity,checkBase::companyCreditHistory,checkBase::bigCompanyIncomeHistory);
        checkTemplate.checkLoanApplication();

    }

}



两种实现方式比较:

第一种实现要每一个要检查的对象都要被创建一个具体的类,而java8的实现可以直接传入“函数接口”。

在示例中声明了一个具体的类,也可以把所有查检方式(具体方法)都声明在CheckBase 类中,根据不同的检查对象直接传入“函数”就可以,这样就避免为每一个检查对象创建一个类。




猜你喜欢

转载自blog.csdn.net/convict_eva/article/details/79287869