学海无涯

导航

Template Method 和 Strategy 策略模式

Template Method 模式和 Strategy 模式所有解决的问题是类似的,通常可以互换使用。不过 Template Mothod 模式使用抽象类来解决问题,而 Strategy 使用接口来解决问题。

Strategy 模式:为了遵循依赖倒置原则(DIP),我们想确保这个通用的算法不要依赖于具体实现,我们想要这个通用算法和具体实都依赖于抽象。

Template Method 模式允许一个通用算法操纵多个可能的具体实现,但是由于Strategy模式完全遵循DIP原则,从而允许每个具体实现都可以被多个不同的通用算法操纵

以下例子中使用Strategy模式,可以实现多种排序算法,需要实现一个新的排序算法,只需要声明一个新的排序算法类。

一、Template Method(模板方法)

使用抽象类实现模板方法模式,把通用算法在抽象类中实现,细节定义为抽象方法,细节的具体实现放在派生类中

优势:所有派生类都能共用通用算法,派生类只需专注于抽象方法的具体实现。

缺点:继承是一种非常强的的关系,派生类不可避免的和他的基类绑定在一起。

Template Method 实现冒泡排序算法:

 

 

namespace DesignPatternsConsoleApp.TemplateMethod
{
    /// <summary>
    /// 模板方法模式,实现冒泡排序
    /// </summary>
    public abstract class BubbleSorter
    {
        private int operations = 0;//次数
        protected int length = 0;
        /// <summary>
        /// 通用算法在抽象类中实现,排序算法实现
        /// </summary>
        /// <returns></returns>
        protected int DoSort()
        {
            operations = 0;
            if (length <= 1)
                return operations;
            for (int nextToLast = length - 2; nextToLast >= 0; nextToLast--)
                for (int index = 0; index <= nextToLast; index++)
                {
                    if (OutOfOrder(index))
                        Swap(index);
                    operations++;
                }
            return operations;
        }
        /// <summary>
        /// 交换数组中两个相邻的值,差异细节在派生类中实现
        /// </summary>
        /// <param name="index"></param>
        protected abstract void Swap(int index);
        /// <summary>
        ///是否满足交换 ,差异细节在派生类中实现
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected abstract bool OutOfOrder(int index);
    }
}

  

namespace DesignPatternsConsoleApp.TemplateMethod
{
    public class IntBubbleSorter : BubbleSorter
    {
        private int[] array = null;
        public int Sort(int[] array)
        {
            this.array = array ?? new int[0];
            length =this.array.Length;
            return DoSort();
        }
        protected override bool OutOfOrder(int index)
        {
            return array[index] > array[index + 1];
        }

        protected override void Swap(int index)
        {
            int temp = array[index];
            array[index] = array[index + 1];
            array[index + 1] = temp;
        }
    }
}

  

namespace DesignPatternsConsoleApp.TemplateMethod
{
    public class DoubleBubbleSorter : BubbleSorter
    {
        private double[] array = null;
        public int Sort(double[] theArray)
        {
            array = theArray;
            length = array.Length;
            return DoSort();
        }
        protected override bool OutOfOrder(int index)
        {
            return array[index] > array[index + 1];
        }

        protected override void Swap(int index)
        {
            double temp = array[index];
            array[index] = array[index + 1];
            array[index + 1] = temp;
        }
    }
}

二、Strategy 策略模式

策略模式是将通用算法放在一个具体类中,把通用算法必须要调用的方法定义在接口中。由于Strategy模式完全遵循DIP原则,从而允许每个具体实现都可以被多个不同的通用算法操纵

 

 

 

namespace DesignPatternsConsoleApp.Strategy
{
    /// <summary>
    /// 冒泡排序算法策略
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BubbleSorter<T>
    {
        private int operations = 0;
        private int length = 0;
        private ISortHandle<T> itsSortHandler = null;

        public BubbleSorter(ISortHandle<T> handle)
        {
            itsSortHandler = handle;
        }

        public ISortHandle<T> ISortHandle
        {
            get => itsSortHandler;
        }

        public int Sort(T[] array)
        {//通用算法,冒泡排序
            itsSortHandler.SetArray(array);
            length = itsSortHandler.Length();
            operations = 0;
            if (length <= 1)
            {
                return operations;
            }
            for (int nextToLast = length - 2; nextToLast >= 0; nextToLast--)
            {
                for (int index = 0; index <= nextToLast; index++)
                {
                    if (itsSortHandler.OutOfOrder(index))
                        itsSortHandler.Swap(index);
                    operations++;
                }
            }
            return operations;
        }
    }
}

  

namespace DesignPatternsConsoleApp.Strategy
{
    /// <summary>
    /// 冒泡排序策略2,如果数组已排序则不再重新排序
    /// </summary>
    public class QuickBubbleSorter<T>
    {
        private int operations = 0;
        private int length = 0;
        private ISortHandle<T> itsSortHandler = null;
        public QuickBubbleSorter(ISortHandle<T> handle)
        {
            itsSortHandler = handle;
        }

        public ISortHandle<T> ISortHandle
        {
            get => itsSortHandler;
        }

        public int Sort(T[] array)
        {
            itsSortHandler.SetArray(array);
            length = itsSortHandler.Length();
            operations = 0;
            if (length <= 1)
                return operations;
            bool thisPassInOrder = false;
            for (int nextToLast = length - 2; nextToLast >= 0 && !thisPassInOrder; nextToLast--)
                for (int index = 0; index <= nextToLast; index++)
                {
                    if (itsSortHandler.OutOfOrder(index))
                    {
                        itsSortHandler.Swap(index);
                        thisPassInOrder = false;
                    }
                    operations++;
                }
            return operations;
        }

    }
}

  

namespace DesignPatternsConsoleApp.Strategy
{
    public interface ISortHandle<T>
    {//通过算法必须要调用的方法
        void Swap(int index);
        bool OutOfOrder(int index);
        int Length();
        void SetArray(T[] array);
    }
}

  

namespace DesignPatternsConsoleApp.Strategy
{
    public class SortHandle<T> : ISortHandle<T> where T : IComparable<T>
    {
        private T[] array = null;
        public int Length()
        {
            return array.Length;
        }

        public bool OutOfOrder(int index)
        {
            return array[index].CompareTo(array[index + 1]) > 0;
        }

        public void SetArray(T[] array)
        {
            this.array = array;
        }

        public void Swap(int index)
        {
            var temp = array[index];
            array[index] = array[index + 1];
            array[index + 1] = temp;
        }
    }
}

  

posted on 2022-11-14 16:03  宁静致远.  阅读(81)  评论(0)    收藏  举报