打败全国百分之99.99的模板方法模式讲解
  E9sWfnfGCxQT 2023年11月02日 28 0



目录

  • 背景:
  • 模板方法定义:
  • 步骤:
  • 初始版: 每个人都抄卷子,然后抄完写自己的答案
  • 第一版:将试卷的题抽象出来
  • 第二版:将每个人回答的部分抽象出来
  • 第三版:将答题步骤封装出来(这里书上写的比较灵活)
  • 版本4:基于大话设计模式上版本三展开想象回归业务,这里的所谓步骤仅仅是答题顺序吗,是不是还有别的可能(如A要先吃饭再睡觉,B要先做第一题再做第二题)
  • 版本5:基于书上的代码是不是可以推断出来只要是至少包含两个方法的代码,都可以使用模板方法(方法个数)
  • 分析
  • 自动化代码:
  • 未来展望:
  • 总结:


背景:

为什么要学习设计模式?
面向对象设计思想分为几层:

Spring相关代码
设计模式
软件七大设计原则
复用扩充维护
封装继承多态
抽象

这样就可以看出来,设计模式处在承上启下的重要位置,只有把设计模式学好,我们才能更加深刻理解Spring。

模板方法定义:

定义一个操作中的算法骨架,而将一些步骤延迟到子类中,模板方法是的子类可以不改变一个算法的结构即可重定义改算法的某些特定步骤。

打败全国百分之99.99的模板方法模式讲解_java

步骤:

业务场景:两个人做一套卷子,两个人有自己的答案。

初始版: 每个人都抄卷子,然后抄完写自己的答案

package com.example.Template.v1;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v1
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 10:26
 * @Version: 1.0
 */

public class Client {
    public static void main(String[] args) {
        TestPaperA   studentA = new TestPaperA();
        studentA.testQueation1();
        studentA.testQueation2();
        studentA.testQueation3();

        TestPaperB   studentB = new TestPaperB();
        studentB.testQueation1();
        studentB.testQueation2();
        studentB.testQueation3();

    }

}
package com.example.Template.v1;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v1
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 09:27
 * @Version: 1.0
 */

public class TestPaperA {
    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子");
        System.out.println("答案:B");
    }


    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语");
        System.out.println("答案:B");
    }


    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色");
        System.out.println("答案:B");
    }


}
package com.example.Template.v1;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v1
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 09:27
 * @Version: 1.0
 */

public class TestPaperB {
    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子");
        System.out.println("答案:A");
    }


    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语");
        System.out.println("答案:A");
    }


    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色");
        System.out.println("答案:A");
    }


}
package com.example.Template.v1;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v1
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 09:27
 * @Version: 1.0
 */

public class TestPaperB {
    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子");
        System.out.println("答案:A");
    }


    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语");
        System.out.println("答案:A");
    }


    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色");
        System.out.println("答案:A");
    }


}

第一版:将试卷的题抽象出来

public class Client {
    public static void main(String[] args) {
        TestPaperA studentA = new TestPaperA();
        studentA.testQueation1();
        studentA.testQueation2();
        studentA.testQueation3();

        TestPaperB studentB = new TestPaperB();
        studentB.testQueation1();
        studentB.testQueation2();
        studentB.testQueation3();

    }

}
package com.example.Template.v2;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v2
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 10:32
 * @Version: 1.0
 */

public class TestPaper {

    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子");

    }


    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语");

    }


    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色");

    }
}
package com.example.Template.v2;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v1
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 09:27
 * @Version: 1.0
 */

public class TestPaperA extends   TestPaper{
    public  void testQueation1(){
      super.testQueation1();
        System.out.println("答案:B");
    }


    public  void testQueation2(){
        super.testQueation2();
        System.out.println("答案:B");


    }


    public  void testQueation3(){
        super.testQueation3();
        System.out.println("答案:B");
    }


}
package com.example.Template.v2;

/**
 * @BelongsProject: JAVAtest
 * @BelongsPackage: com.example.Template.v1
 * @Author: GuoYuan.Zhao
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-09-14 09:27
 * @Version: 1.0
 */

public class TestPaperB {
    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子");
        System.out.println("答案:A");
    }


    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语");
        System.out.println("答案:A");
    }


    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色");
        System.out.println("答案:A");
    }


}

第二版:将每个人回答的部分抽象出来

public class Client {
    public static void main(String[] args) {
        TestPaperA studentA = new TestPaperA();
        studentA.testQueation1();
        studentA.testQueation2();
        studentA.testQueation3();

        TestPaperB studentB = new TestPaperB();
        studentB.testQueation1();
        studentB.testQueation2();
        studentB.testQueation3();

    }
public class TestPaper {

    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子"+"答案"+ getAnswer1());

    }

    public String getAnswer1(){
        return "A";
    }



    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语"+getAnswer2());

    }


    public String getAnswer2(){
        return "A";
    }

    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色"+getAnswer3());

    }

    public String getAnswer3(){
        return "A";
    }
}
public class TestPaperA extends TestPaper {
    public String getAnswer1(){
        System.out.println("A");
        return "A";
    }

    public String getAnswer2(){
        System.out.println("A");

        return "A";
    }

    public String getAnswer3(){
        System.out.println("A");

        return "A";
    }


}
public class TestPaperB  extends  TestPaper {
    public String getAnswer1(){
        System.out.println("B");

        return "B";
    }

    public String getAnswer2(){
        System.out.println("B");

        return "B";
    }

    public String getAnswer3(){
        System.out.println("B");

        return "B";
    }


}

第三版:将答题步骤封装出来(这里书上写的比较灵活)

public class Client {
    public static void main(String[] args) {
        TestPaperA studentA = new TestPaperA();
        studentA.templateMethod();

        TestPaperB studentB = new TestPaperB();
        studentB.templateMethod();

    }

}
public class TestPaper {

    public  void testQueation1(){
        System.out.println("你喜欢吃啥东西呢?   A:苹果  B:香蕉    c:橙子"+"答案"+ getAnswer1());

    }

    public String getAnswer1(){
        return "A";
    }



    public  void testQueation2(){
        System.out.println("你喜欢的学科是啥呢?   A:语文  B:数学    c:英语"+getAnswer2());

    }


    public String getAnswer2(){
        return "A";
    }

    public  void testQueation3(){
        System.out.println("你喜欢的颜色是啥呢?   A:红色  B:绿色    c:蓝色"+getAnswer3());

    }

    public String getAnswer3(){
        return "A";
    }


    public  void   templateMethod(){
        this.testQueation1();
        this.testQueation2();
        this.testQueation3();
    }
}
public class TestPaperA extends TestPaper {
    public String getAnswer1(){
        System.out.println("A");
        return "A";
    }

    public String getAnswer2(){
        System.out.println("A");

        return "A";
    }

    public String getAnswer3(){
        System.out.println("A");

        return "A";
    }


}
public class TestPaperB  extends TestPaper {
    public String getAnswer1(){
        System.out.println("B");

        return "B";
    }

    public String getAnswer2(){
        System.out.println("B");

        return "B";
    }

    public String getAnswer3(){
        System.out.println("B");

        return "B";
    }


}

版本4:基于大话设计模式上版本三展开想象回归业务,这里的所谓步骤仅仅是答题顺序吗,是不是还有别的可能(如A要先吃饭再睡觉,B要先做第一题再做第二题)

版本5:基于书上的代码是不是可以推断出来只要是至少包含两个方法的代码,都可以使用模板方法(方法个数)

分析

package com;
 
abstract class AbstractClass {
	public abstract void PrimitiveOperation1();
	public abstract void PrimitiveOperation2();
	
	public void templateMethod(){
		PrimitiveOperation1();
		PrimitiveOperation2();
	    System.out.println(    );
	}
}
****************
package com;
 
public class ConcreteClassA extends AbstractClass{
 
	@Override
	public void PrimitiveOperation1() {
		// TODO Auto-generated method stub
		System.out.println("A的具体方法1");
	}
 
	@Override
	public void PrimitiveOperation2() {
		// TODO Auto-generated method stub
		System.out.println("A的具体方法2");
	}
 
}
*******************
package com;
 
public class ConcreteClassB extends AbstractClass{
	@Override
	public void PrimitiveOperation1() {
		// TODO Auto-generated method stub
		System.out.println("B的具体方法1");
	}
 
	@Override
	public void PrimitiveOperation2() {
		// TODO Auto-generated method stub
		System.out.println("B的具体方法2");
	}
 
}
****************
 
package com;
 
public class Main {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		AbstractClass c;
		c=new ConcreteClassA();
		c.templateMethod();
		c=new ConcreteClassB();
		c.templateMethod();
		
	}
 
}

看上边的代码是不是可以激发你的想象力吗?
模板方法中的templateMethod 方法中打印最后一行空格给大家留下了想象的空间,是第三个题目还是为了让输入结果错开,看着分界线明显呢。

概念里边说的骨架,
1、并不仅仅是templateMethod 中定义了执行方法的顺序
2、还有这几个方法本身就是骨架,子类大概率会重写抽象类中的抽象方法(方法名一样,返回类型一样,这不算是骨架吗)

体现了依赖倒置:
templateMethod 中调用了PrimitiveOperation2和PrimitiveOperation1,但是
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();

这俩方法在父类中根本没有具体实现,只有真正到子类的时候,去执行子类中的具体方法,
倒置是什么意思?
细节依赖于抽象:子类方法起名要按照父类起,且在客户端子类对象.templateMethod (),运行起来要按照父类templateMethod 方法的代码步骤执行。
是抽象不依赖于细节:抽象类中的方法名和templateMethod 中的方法先后顺序不会因为子类发生变化而改变。

自动化代码:

子类可以抽出模板:

public class ConcreteClassX extends AbstractClass{
	@Override
	public void PrimitiveOperation1() {
		//通过前端传过来
	}
 
	@Override
	public void PrimitiveOperation2() {
		//通过前端传过来
	}
 
}

可以看到客户端也有重复性代码:
AbstractClass c;
c=new ConcreteClassA();
c.templateMethod();
c=new ConcreteClassB();
c.templateMethod();
也可以通过模板实现

未来展望:

客户端部分可以拆成和策略模式一样,任意组合创建不同的子类对象。
再进一步灵活加上工厂方法,就可以自动配置组合方式。(客户端传参)

总结:

从版本1开始,我们一步步增加灵活性,多维度思考,主要围绕复用扩充维护三方面考虑,代码越来越灵活。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   55   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   110   0   0 Java
  8s1LUHPryisj   2024年05月17日   46   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
E9sWfnfGCxQT