设计模式之模板方法模式

释放双眼,带上耳机,听听看~!

1.术语

 1)操作和方法的区别

       操作是方法的一种抽象,方法是操作的实现;同种操作可能由不同的方法实现。

 2)算法是一个接收输入和产生输出的过程,算法作用于一些方法,一个算法过程可能包括多个操作和方法。

2.模板方法模式的定义

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

3.模板方法模式的意图

       在一个方法里实现一个算法,并推迟定义算法中的某些步骤,从而让其他类重新定义它们。

4.模板方法模式解读

 1)UML图

设计模式之模板方法模式

  2)角色

  • 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。

  • 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。


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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
1/// <summary>
2    /// 抽象类
3    /// </summary>
4    public abstract class AbstractClass
5    {
6        // 一些抽象行为,放到子类去实现
7        public abstract void PrimitiveOperation1();
8        public abstract void PrimitiveOperation2();
9
10        /// <summary>
11        /// 模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们推迟到子类去实现。
12        /// </summary>
13        public void TemplateMethod()
14        {
15            PrimitiveOperation1();
16            PrimitiveOperation2();
17            Console.WriteLine("Done the method.");
18        }
19    }
20
21    /// <summary>
22    /// 具体类,实现了抽象类中的特定步骤
23    /// </summary>
24    public class ConcreteClassA : AbstractClass
25    {
26        /// <summary>
27        /// 与ConcreteClassB中的实现逻辑不同
28        /// </summary>
29        public override void PrimitiveOperation1()
30        {
31            Console.WriteLine("Implement operation 1 in Concreate class A.");
32        }
33
34        /// <summary>
35        /// 与ConcreteClassB中的实现逻辑不同
36        /// </summary>
37        public override void PrimitiveOperation2()
38        {
39            Console.WriteLine("Implement operation 2 in Concreate class A.");
40        }
41    }
42
43    /// <summary>
44    /// 具体类,实现了抽象类中的特定步骤
45    /// </summary>
46    public class ConcreteClassB : AbstractClass
47    {
48        /// <summary>
49        /// 与ConcreteClassA中的实现逻辑不同
50        /// </summary>
51        public override void PrimitiveOperation1()
52        {
53            Console.WriteLine("Implement operation 1 in Concreate class B.");
54        }
55
56        /// <summary>
57        /// 与ConcreteClassA中的实现逻辑不同
58        /// </summary>
59        public override void PrimitiveOperation2()
60        {
61            Console.WriteLine("Implement operation 2 in Concreate class B.");
62        }
63    }
64
65//客户端调用
66class Program
67    {
68        static void Main(string[] args)
69        {
70            // 声明抽象类
71            AbstractClass c;
72
73            // 用ConcreteClassA实例化c
74            c = new ConcreteClassA();
75            c.TemplateMethod();
76
77            // 用ConcreteClassB实例化c
78            c = new ConcreteClassB();
79            c.TemplateMethod();
80
81            Console.Read();
82        }
83    }
84

运行结果

设计模式之模板方法模式
5. 模式总结
优点
1)模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。
2)子类实现算法的某些细节,有助于算法的扩展。
3) 通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。

  1. 适用场景

1)在某些类的算法中,用了相同的方法,造成代码的重复。
2)控制子类扩展,子类必须遵守算法规则。

    3)排序算法是模板方法模式的经典范例。

7.举例

 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
1/// <summary>
2    /// 抽象类,定义冒泡排序的骨架
3    /// </summary>
4    public abstract class BubbleSorter
5    {
6        private int operations = 0;
7        protected int length = 0;
8
9        /// <summary>
10        /// 冒泡排序算法
11        /// </summary>
12        /// <returns></returns>
13        protected int DoSort()
14        {
15            operations = 0;
16            if (length <= 1)
17            {
18                return operations;
19            }
20
21            for (int nextToLast = length - 2; nextToLast >= 0; nextToLast--)
22            {
23                for (int index = 0; index <= nextToLast; index++)
24                {
25                    if (OutOfOrder(index))
26                    {
27                        Swap(index);
28                    }
29
30                    operations++;
31                }
32            }
33
34            return operations;
35        }
36
37        /// <summary>
38        /// 留给子类实现的交换位置方法
39        /// </summary>
40        /// <param name="index"></param>
41        protected abstract void Swap(int index);
42        /// <summary>
43        /// 留给子类实现的比较方法
44        /// </summary>
45        /// <param name="index"></param>
46        /// <returns></returns>
47        protected abstract bool OutOfOrder(int index);
48    }
49
50    /// <summary>
51    /// 整型类型的冒泡算法实现
52    /// </summary>
53    public class IntBubbleSorter:BubbleSorter
54    {
55        private int[] array = null;
56
57        /// <summary>
58        /// 用冒泡算法排序
59        /// </summary>
60        /// <param name="theArray"></param>
61        /// <returns></returns>
62        public int Sort(int[] theArray)
63        {
64            array = theArray;
65            length = array.Length;
66            // 调用冒泡算法
67            return DoSort();
68        }
69
70        /// <summary>
71        /// 实现冒泡算法中的交换操作
72        /// </summary>
73        /// <param name="index"></param>
74        protected override void Swap(int index)
75        {
76            int temp = array[index];
77            array[index] = array[index + 1];
78            array[index + 1] = temp;
79        }
80
81        /// <summary>
82        /// 实现冒泡算法中的比较操作
83        /// </summary>
84        /// <param name="index"></param>
85        /// <returns></returns>
86        protected override bool OutOfOrder(int index)
87        {
88            return (array[index] > array[index + 1]);
89        }
90    }
91
92    /// <summary>
93    /// 浮点数类型的冒泡算法
94    /// </summary>
95    public class FloatBubbleSorter:BubbleSorter
96    {
97        private float[] array = null;
98
99        /// <summary>
100        /// 用冒泡算法排序
101        /// </summary>
102        /// <param name="theArray"></param>
103        /// <returns></returns>
104        public int Sort(float[] theArray)
105        {
106            array = theArray;
107            length = array.Length;
108            // 调用冒泡算法
109            return DoSort();
110        }
111
112        /// <summary>
113        /// 实现冒泡算法中的交换操作
114        /// </summary>
115        /// <param name="index"></param>
116        protected override void Swap(int index)
117        {
118            float temp = array[index];
119            array[index] = array[index + 1];
120            array[index + 1] = temp;
121        }
122
123        /// <summary>
124        /// 实现冒泡算法中的比较操作
125        /// </summary>
126        /// <param name="index"></param>
127        /// <returns></returns>
128        protected override bool OutOfOrder(int index)
129        {
130            return (array[index] > array[index + 1]);
131        }
132    }
133
134//客户端调用
135class Program
136    {
137        static void Main(string[] args)
138        {
139
140            // 对整型数组排序
141            int[] intArray = new int[]{5, 3, 12, 8, 10};
142            BubbleSorter.IntBubbleSorter sorter = new BubbleSorter.IntBubbleSorter();
143            sorter.Sort(intArray);
144            foreach (int item in intArray)
145            {
146                Console.Write(item+" ");
147            }
148
149            Console.WriteLine("");
150
151            // 对浮点数排序
152            float[] floatArray = new float[] { 5.0f, 3.0f, 12.0f, 8.0f, 10.0f };
153            BubbleSorter.FloatBubbleSorter floatSorter = new BubbleSorter.FloatBubbleSorter();
154            floatSorter.Sort(floatArray);
155            foreach (float item in floatArray)
156            {
157                Console.Write(item + " ");
158            }
159
160            Console.Read();
161        }
162    }
163

运行结果

设计模式之模板方法模式

 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
1/************************************************************************/
2/*             模板方法模式                                */
3/************************************************************************/
4
5/*
6   将重复的行为在父类中抽象,具体实现在子类种完成,而行为的调用代码在父类中完成
7   利用多态原理,实际的调用的是子类的行为
8*/
9
10
11/*这里以A、B两人答同一份试卷为例*/
12
13#include<iostream>
14using namespace std;
15
16class TestPaper
17{
18public:
19  /*A和B都具有答题的行为,但是具体的行为的表现却不一样*/
20  virtual void Answer1() = 0;
21  virtual void Answer2() = 0;
22
23  void Question1()
24  {
25      cout<<"凤姐是不是女人?    A.是   B.不是"<<endl;
26      Answer1();
27  }
28
29  void Question2()
30  {
31      cout<<"如果世界上只剩下凤姐和你,你会取她吗?     A.我宁愿自杀   B.为了人类哥从了"<<endl;
32      Answer2();
33  }
34};
35
36
37//A的答题试卷
38class TestPaperA : public TestPaper
39{
40public:
41  void Answer1()
42  {
43      cout<<"A"<<endl;
44  }
45
46  void Answer2()
47  {
48      cout<<"A"<<endl;
49  }
50};
51
52//B的答题试卷
53class TestPaperB : public TestPaper
54{
55public:
56  void Answer1()
57  {
58      cout<<"B"<<endl;
59  }
60
61  void Answer2()
62  {
63      cout<<"B"<<endl;
64  }
65};
66
67
68void main()
69{
70  cout<<"A的试卷"<<endl;
71  TestPaper * A = new TestPaperA();
72  A->Question1();
73  A->Question2();
74
75  cout<<"................................................................................"<<endl;
76
77  cout<<"B的试卷"<<endl;
78  TestPaperB *B = new TestPaperB();
79  B->Question1();
80  B->Question2();
81}
82
83
84
85

1
2
1 运行结果:
2

给TA打赏
共{{data.count}}人
人已打赏
安全运维

基于spring boot和mongodb打造一套完整的权限架构(五)【集成用户模块、菜单模块、角色模块】

2021-12-11 11:36:11

安全运维

Ubuntu上NFS的安装配置

2021-12-19 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索