模板模式

###定义
模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤。在软件工程中,它是一种软件设计模式,和C++模板没有关连。

结构图

模板模式结构图

抽象模板(Abstract Template)角色有如下责任:

   定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。

  定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

  具体模板(Concrete Template)角色又如下责任:
  实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

模板模式在生活中的应用

在生活中随处可以看到模板模式的实现,遥控器的设计,只给了一个按键就是一种实现的算法,可是把他封装起来,在模板上会有所有的方法,比如调节音量和频道,模板就是封装算法的一种规范,在生活中,我们也需要把我们的一些秘密封装起来,比如登陆页面,只要你输入密码就可以触发验证的方法,比对正确才能够登录进去。
再设计模式中,herberate的设计也是运用了模板模式,在连接的时候,把繁琐的连接和断开,验证等操作封装起来,形成了基本的文件配置就可以连接数据库并提供不同的事务管理配置,降低了耦合度,提高了开发效率。

模板模式和策略模式的比较

  1. 模板定义个一个算法的大纲,而由子类定义其中某些步骤的内容,算法的结构不改变,而策略通过对象组合让客户选择算法实现,放弃了对算法的控制
  2. 模板由于使用了继承,实现了代码的复用,实现了所有子类之间的共享,而策略采用委托模板,使用了组合对象,更加有弹性和可扩展性,客户可以在运行的时候选择不同的策略对象去实现不同的算法

    代码实现

    定义抽象模板
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package templatemethodtest1;
    public abstract class CaffeineBeverageWithHook {
    void prepareRecipe(){
    boilWater();
    brew();
    pourInCup();
    if(customerWantsCondiments()){
    addCondiments();
    }
    }
    private boolean customerWantsCondiments() {
    // TODO Auto-generated method stub
    return true;
    }
    private void pourInCup() {
    // TODO Auto-generated method stub
    System.out.println("Pouring into cup");
    }
    abstract void brew();
    abstract void addCondiments();
    void boilWater(){
    System.out.println("Boiling water");
    }
    }

实现具体的模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package templatemethodtest1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CoffeeWithHook extends CaffeineBeverageWithHook{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Dripping Coffee through filter");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("Adding Suger and Mink");
}
public boolean customerWantsCondiments() {
// TODO Auto-generated method stub
String answer=getUserInput();
if(answer.toLowerCase().startsWith("y")){
return true;
}else{
return false;
}
}
private String getUserInput() {
// TODO Auto-generated method stub
String answer=null;
System.out.println("Would you like milk and sugar with your xoffee(y/n)?");
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
try{
answer=in.readLine();
}catch(IOException e){
System.out.println("IO err trying to read your answer");
}
if(answer==null){
return "no";
}
return answer;
}
}

测试

1
2
3
4
5
6
7
8
9
10
package templatemethodtest1;
public class BeverageTestDrive {
public static void main(String[] args) {
CoffeeWithHook coffeeHook=new CoffeeWithHook();
System.out.println("Makeing coffee...");
coffeeHook.prepareRecipe();
}
}

结果:
Makeing coffee…
Boiling water
Dripping Coffee through filter
Pouring into cup
Adding Suger and Mink

模板测试算法排列

通过封装算法的排列,实现了简洁的代码和实现,对面向对像的封装有进一步的接触,

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package templatemethodtest;
public class Duck implements Comparable {
String name;
int weight;
public Duck(String name, int weight) {
super();
this.name = name;
this.weight = weight;
}
public String toString(){
return name+"weight"+" "+weight;
}
@Override
public int compareTo(Object object) {
// TODO Auto-generated method stub
Duck otherDuck=(Duck) object;
if(this.weight<otherDuck.weight){
return -1;
}else if(this.weight==otherDuck.weight){
return 0;
}else{
return 1;
}
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package templatemethodtest;
import java.util.Arrays;
public class DuckSortTestDrive {
public static void main(String[] args) {
Duck [] ducks={
new Duck("Daffy",8),
new Duck("Dewey",2),
new Duck("Howard",7),
new Duck("Loule",2),
new Duck("Donald",10),
new Duck("Huey",2)
};
System.out.println("Before sorting: ");
display(ducks);
Arrays.sort(ducks);
System.out.println("\n After sorting: ");
display(ducks);
}
private static void display(Duck[] ducks) {
// TODO Auto-generated method stub
for(int i=0;i<ducks.length;i++){
System.out.println(ducks[i]);
}
}
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Before sorting:
Daffyweight 8
Deweyweight 2
Howardweight 7
Louleweight 2
Donaldweight 10
Hueyweight 2
After sorting:
Deweyweight 2
Louleweight 2
Hueyweight 2
Howardweight 7
Daffyweight 8
Donaldweight 10

总结

在生活中也有很多的方法思维是这样的,当你要用到那个知识点的时候你才去翻阅,而不用一直放在你的记忆力,这样的话很容易造成知识混乱,这就是所谓的内聚吧,所以我们在生活中也处处用到模板模式,而考试的知识抽查需要用到策略模式,把所有的问题都需要设计,这样才能够不变应万变,正所谓,你不用来找我,我去找你,就是这个道理吧。

文章目录
  1. 1. 结构图
    1. 1.0.1. 抽象模板(Abstract Template)角色有如下责任:
  2. 1.1. 模板模式在生活中的应用
  • 2. 模板模式和策略模式的比较
    1. 2.1. 代码实现
      1. 2.1.1. 模板测试算法排列
      2. 2.1.2. 代码实现
    2. 2.2. 总结
  • ,