模式十:模板方法模式

   10.1模板方法模式定义

   在一个方法中定义一个算法的框架,而将一些步骤延迟到子类中。模板方法可以使得子类在不改变算法结构的情况下,重新定义算法中的某些步骤。      

  10.2模板方法模式UML类图:

    模式方法的定义:void TemplateMethod()。模式方法不能声明成virtual是因为当然不允许子类改变算法的框架。

  10.3应用场景:

   模块方法在定义整个算法的框架时特别有用,它甚至可以说是用得最多的设计模式之一。当我们某一个算法有公共步骤可能被需要子类用到,而某些步骤是必需由子类实现的,这时我们就可以利用模板方法模式。例如我们制作咖啡的算法,冲水这个动作是所有咖啡都要用到的,而放调料这个算法是由不同的咖啡(子类)来决定的,因为不同的咖啡放的是不同的调料,这时我们就可以将咖啡制作定义成一个模块方法,其中调用抽象方法放调料和非抽象方法冲水。

 

10.4模板方法模式分析与实现(c#描述):

//最简单的模板方法示例

    namespace SimpleTemplateMethod

    {

        //苹果类,里面包含模块方法。

        public abstract class Apple

        {

            public void Prepare()//模板方法,一系列方法的组合。

            {

                this.Wash();

                this.Cut();

            }

 

            public void Wash()//洗苹果的动作对所有苹果来说都一样,因此这里设为非抽象方法,被所有子类所共用。

            {

                Console.WriteLine("把苹果洗了,呵呵。");

            }

 

            public abstract void Cut();//抽象方法,由子类决定如何切苹果。

            //这里又是让子类决定,是不是跟工厂方法的让子类决定很相似呢?呵呵。其实,工厂方法就是模板方法的一个特例。因为工厂方法让子类决定的是类的创建,而模板方法让子类决定的是算法的步骤。

 

        }

 

        //红苹果,其切法为每个苹果切成2块。

        public class RedApple : Apple

        {

            public override void Cut()

            {

                Console.WriteLine("把苹果切成2块。");

            }

        }

 

        //黄苹果,其切法为每个苹果切成4块。

        public class YellowApple : Apple

        {

            public override void Cut()

            {

                Console.WriteLine("把苹果切成4块。");

            }

        }

 

        //调用类

        public class SimpleTemplateMethod_Test

        {

            public static void Do()

            {

                Apple lobj_Apple = new RedApple();

                lobj_Apple.Prepare();//红苹果的切法是每个苹果切成2块。

 

                lobj_Apple = new YellowApple();

                lobj_Apple.Prepare();//黄苹果的切法是每个苹果切成4块。

            }

        }

    }

 

    //带钩子的模板方法示例。钩子在这里是用于决定算法流程的一个方法。

    namespace TemplateMethodWithHook

    {

 

        public abstract class Apple

        {

            public void Prepare()

            {

                this.Wash();

                if (this.CanCut())//这里由于由子类决定是否可以进行切割,所以相当于可以由子类决定是否改变算法流程。

                {

                    this.Cut();

                }

            }

 

            public void Wash ()

            {

                Console.WriteLine("把苹果洗了,呵呵。");

            }

 

            public abstract void Cut();

 

            //钩子,子类通过对其控制可以改变算法流程。

            public virtual bool CanCut()

            {

                return true;//默认为需要对苹果进行切分。

            }

 

        }

 

        //红苹果,其切法为每个苹果切成2块。

        public class RedApple : Apple

        {

            public override void Cut()

            {

                Console.WriteLine("把苹果切成2块。");

            }

        }

 

        //黄苹果,其切法为每个苹果切成4块。

        public class YellowApple : Apple

        {

            public override void Cut()

            {

                Console.WriteLine("把苹果切成4块。");

            }

 

            public override bool CanCut()//黄苹果不允许将苹果进行切分。

            {

                return false;

            }

        }

 

 

        //调用类

        public class TemplateMethodWithHook_Test

        {

            public static void Do()

            {

                Apple lobj_Apple = new RedApple();

                lobj_Apple.Prepare();//红苹果的切法是每个苹果切成2块。

 

                lobj_Apple = new YellowApple();

                lobj_Apple.Prepare();//红苹果的切法是每个苹果切成4块,但由于黄苹果使用的钩子说不切了,所以这里不对苹果进行切分。

            }

        }

    }

 

    namespace TemplateMethodInCSharp

    {

        public class Bird : IComparable

        {

            private string _Name;

 

            public string Name

            {

                get { return _Name; }

                set { _Name = value; }

            }

 

            private int _Weight;           

 

            public Bird(string astg_Name,int aint_Weight)

            {

                this._Name = astg_Name;

                this._Weight = aint_Weight;

            }

 

            public int CompareTo(object obj)//CompareTo为模板方法中的某个步骤,这里我们定义以鸟的排序规则:根据重量排序,重量较轻的顺序在前,重量较重的顺序在后。

            {

                if (this._Weight > ((Bird)obj)._Weight) return 1;

                else if (this._Weight == ((Bird)obj)._Weight) return 0;

                else  return -1;

            }

        }

 

        //调用类

        public class TemplateMethodInCSharp_Test

        {

            public static void Do()

            {

               //下面我们利用ArraySort模板方法对Bird进行排序。

                Bird[] arr_Birds = new Bird[] { new Bird("Andy",3), new Bird("Cherry",2), new Bird("Tom",5) };

                Array.Sort(arr_Birds);

                for (int lint_LoopCount = 0; lint_LoopCount < arr_Birds.Length; lint_LoopCount++)

                {

                    Console.WriteLine(arr_Birds[lint_LoopCount].Name);

                }

 

                //模板方法说的是利用继承让子类实现父类中的抽象算法步骤,这里没有用到继承为什么也是模板方法呢?请注意,模板方法的实现形态可以多种多样的,这种算是模板方法的变体吧。

            }

        }

 }

 

    这个模式用来创建一个算法的模板。什么是模板?实际上模板就是一个方法,这个方法将算法定义成一组步骤,其中的任何步骤都要以是抽象的,由子类进行实现,这样就要以保证算法的整体框架不变,然后由子类提供部分实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值