设计模式笔记之 -Template Method & Strategy

Template Method

       通过抽象分离有共性的方法放入基类中,从而完成通用算法,将所有实现都交给该基类的抽象方法。

       运用此模式主要在于建立抽象基类,制定抽象方法。

 

注意:不要滥用模式,如果把一个简单的问题复杂话了,那还不如不用模式,把一个简单的方法放在抽象基类里,并不能带来什么好处,反而增加了代码的复杂性。

 

冒泡排序的例子:

      

 1/// <summary>
 2    /// Template Method 的冒泡排序的抽象基类
 3    /// </summary>

 4    public abstract class BubbleSorter
 5    {
 6        private int operations = 0;
 7        protected int length = 0;
 8 
 9        protected int DoSort()
10        {
11            operations = 0;
12            if(length <= 1return operations;
13
14            for(int nextToLast = length-2;nextToLast >=0;nextToLast--)
15            {
16                for(int index =0; index<=nextToLast; index++)
17                {
18                    if(OutOfOrder(index))
19                        Swap(index);
20                    operations++;
21                }

22            }

23
24            return operations;
25        }

26
27        protected abstract void Swap(int index);
28        protected abstract bool OutOfOrder(int index);
29    }

30
31
32/// <summary>
33    /// 整数型冒泡排序的实现类
34    /// </summary>

35    public class IntBubbleSorter : BubbleSorter
36    {
37        public IntBubbleSorter()
38        {
39        }

40
41        private int[] array = null;
42        public int Sort(int[] theArray)
43        {
44            this.array = theArray;
45            base.length = array.Length;
46            return base.DoSort();
47        }

48
49        protected override void Swap(int index)
50        {
51            int temp = this.array[index];
52            this.array[index] = array[index+1];
53            array[index + 1= temp;
54        }

55
56
57        protected override bool OutOfOrder(int index)
58        {
59            return (array[index]<array[index+1]);
60        }

61
62
63
64    }

 

这种模式是经典的重用形式中的一种,其通用算法放置在基类中,并且通过继承在不同具体上下文中实现该通用算法。但是这里的代价就是派生类必须与其基类绑定在一起,如要使派生类不再绑定基类,则需要使用Strategy模式。

 

Strategy

       可以看到上面的排序类违反了依赖倒置原则(DIP),那么把Template Method模式变型,通过接口的桥接作用实现解耦合,如下使用Strategy模式的冒泡排序:

 

 1/// <summary>
 2    /// 冒泡排序
 3    /// </summary>

 4    public class BubbleSorter
 5    {
 6        private int operations = 0;
 7        private int length = 0;
 8        private ISortHandle itsSortHandle = null;
 9
10        public BubbleSorter(ISortHandle handle)
11        {
12            itsSortHandle = handle;
13        }

14
15        /// <summary>
16        /// 开始排序
17        /// </summary>
18        /// <param name="upOrDown">是正序还是倒序</param>
19        /// <returns>返回处理的次数</returns>

20        public int Sort(bool upOrDown)
21        {
22            length = itsSortHandle.Length();
23            operations = 0;
24            if(length <= 1)
25                return operations;
26
27            for(int nextToLast = length-2; nextToLast>=0;nextToLast--)
28            {
29                for(int index=0;index <= nextToLast;index++)
30                {
31                    if(itsSortHandle.OutOfOrder(index) == upOrDown)
32                        itsSortHandle.Swap(index);
33                    operations++;
34                }

35            }

36
37            return operations;
38        }

39
40        /// <summary>
41        /// 开始排序
42        /// </summary>
43        /// <param name="array">传入需要排序的对象</param>
44        /// <param name="upOrDown">是正序还是倒序</param>
45        /// <returns>返回处理的次数</returns>

46        public int Sort(object array , bool upOrDown)
47        {
48            itsSortHandle.SetArray(array);
49            return Sort(upOrDown);
50        }

51
52
53    }
//class

 

 

 1/// <summary>
 2    ///    提供排序的接口函数
 3    /// </summary>

 4    public interface ISortHandle
 5    {
 6        void Swap(int index);
 7        bool OutOfOrder(int index);
 8        int Length();
 9        void SetArray(object array);
10    }

 

 

 1    /// <summary>
 2    /// IntSortHandle 的摘要说明。
 3    /// </summary>

 4    public class IntSortHandle : ISortHandle
 5    {
 6        private int[] array = null;
 7        public IntSortHandle(int[] inValue)
 8        {
 9            this.array = inValue;
10        }

11
12        public IntSortHandle()
13        {
14        }

15
16        public void Swap(int index)
17        {
18            int temp = array[index];
19            array[index] = array[index + 1];
20            array[index+1= temp;
21        }

22
23        public void SetArray(object array)
24        {
25            this.array = (int[])array;
26        }

27
28        public bool OutOfOrder(int index)
29        {
30            return (array[index] > array[index + 1]);
31        }

32
33        public int Length()
34        {
35            if(null == this.array)
36                throw new Exception("数组还没赋值");
37            return array.Length;
38        }

39
40        public int[] GetArray()
41        {
42            return this.array;
43        }

44
45    }

 

 

 1    /// <summary>
 2    /// BubbleSorter_Test 的摘要说明。
 3    /// </summary>

 4    [TestFixture]
 5    public class BubbleSorter_Test
 6    {
 7        public BubbleSorter_Test()
 8        {
 9        }

10
11        [Test]
12        public void Test_IntSort()
13        {
14            int[] invalue = new int[]{3,5,2,7,8,1,9};
15            int[] result1  = new int[]{1,2,3,5,7,8,9};
16            int[] result2  = new int[]{9,8,7,5,3,2,1};
17
18            IntSortHandle ish = new IntSortHandle(invalue);
19            BubbleSorter bs = new BubbleSorter(ish);
20
21            Console.WriteLine("交换的次数:" + bs.Sort(true));
22            Assert.AreEqual(result1,ish.GetArray());
23
24            Console.WriteLine("交换的次数2:" + bs.Sort(invalue,false));
25            Assert.AreEqual(result2,ish.GetArray());
26        }

27    }

 

在这里需要排序的类对排序实现类一无所知,它只知道自己继承自接口,需要关系的只是实现接口方法即可,这样就大大提高了类的实用性,如果在自定义类中需要实现排序功能,那么它只需要继承相应的接口即可,这没有与高层算法的依赖。

 

结论:

       Template MethodStrategy模式都可以用来分离高层算法和低层的具体实现细节,都允许高层算法独立于它的具体实现而重用,此外Strategy还提供了具体实现细节独立于高层算法的重用,不过为此付出的代价就是代码的复杂性提高了,增加了运行开销。

posted on 2005-09-12 18:10  dragonpro  阅读(478)  评论(0编辑  收藏  举报

Free Web Counter