策略模式

来源:互联网 发布:匈牙利命名法 数组 编辑:程序博客网 时间:2024/05/29 09:14

策略模式

 

前言

 

接着好几天前的设计模式再写一篇,不知道谁看过<<男人帮>>这部电视剧,黄磊老师还有红雷大哥演的,里面有以下经典台词:

 

(1)自从我们睁开眼睛看这个世界的第一天起, 我们看到的就只有两种人,男人和女人。 他们分属于两大不同的阵营,为了彻底收服对方,大家互相往死里掐。 

(2)根据一个遥远的传说,说有一种东西叫爱情,可以彻底终结这场战争。于是大家纷纷的赶紧去寻找,赶紧去幻想, 找到头破血流才发现,原来这个感情也是另一些人在书房里炮制出来的。 于是大家更加绝望,更加痛苦,更加互相的往死里掐。 

 

 

 

场景案例

 

尤其是上面这几句,让我想起了一同学和他一女朋友的故事,一次活动中,某某哥认识了某某嫂,哪个一见钟情啊,简直是看不见某某嫂就吃不下饭去,写不下代码,在追求中没少费工夫,比如:送个小礼物,请客吃饭,搞点小浪漫等等.

 

(1)第一阶段赠送小礼物代码如下:

       

 //第一阶段 送小礼物        public static void SendGift()        {            Console.WriteLine("送给女方精美小礼物!");        }         static void Main(string[] args)        {            //第一阶段             SendGift();        } 

(2)此时,通过送精美小礼物女方已经愿意和男方接触,这时就可以一起吃饭了了,代码如下:

 

//第一阶段 送小礼物        public static void SendGift()        {            Console.WriteLine("送给女方精美小礼物!");        }         //添加 第二阶段 请客吃饭        public static void Eat()        {            Console.WriteLine("请女生吃牛排!");        }         static void Main(string[] args)        {            //第一阶段             //SendGift(); //此时第一阶段已经不需要了所以注销掉进入第二阶段             //第二阶段            Eat();        } 

(3)经过之前两个阶段的接触,两个人已经在一起了,在一起就避免不了在热恋中经历一些浪漫的事情,所以第三阶段就是:制造浪漫,代码如下:

 

//第一阶段 送小礼物        public static void SendGift()        {            Console.WriteLine("送给女方精美小礼物!");        }         //添加 第二阶段 请客吃饭        public static void Eat()        {            Console.WriteLine("请女生吃牛排!");        }         //添加 第三阶段 浪漫:烛光晚餐等待女友        public static void Romantic()        {            Console.WriteLine("精心制作了红酒、晚餐与蜡烛,等待女友回家!");        }         static void Main(string[] args)        {            //第一阶段             //SendGift(); //此时第一阶段已经不需要了所以注销掉进入第二阶段             //第二阶段            //Eat(); //此时第二阶段也已经经过,所以注销掉、进入第三阶段             //第三阶段            Romantic();        } 

看了某某哥追某某嫂的经过后,我们会发现,每当进入一个新阶段的时候,我们就需要去修改我们的代码,加入新的追女策略,并且将main函数中的调用修改成进入新的阶段,那么我们怎么样能避免,在进入新阶段后不去修改调用的代码呢?当然这个肯定难不倒你,代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace 策略模式{    class Program    {            //第一阶段 送小礼物        public static void SendGift()        {            Console.WriteLine("送给女方精美小礼物!");        }        //第二阶段 请客吃饭         public static void Eat()        {            Console.WriteLine("请女生吃牛排");        }         //第三阶段 搞点浪漫         public static void Romantic()        {            Console.WriteLine("精心制作了红酒、晚餐与蜡烛,等待女友回家!");        }        static void Main(string[] args)        {            Console.WriteLine("现在是第几阶段?:");             string level = Console.ReadLine();             switch (level)            {                case "one"://第一阶段                     SendGift();                    break;                case "two"://第二阶段                    Eat();                    break;                case "three": //第三阶段                    Romantic();                    break;                default:                    Console.WriteLine("没这个打算凑什么热闹?");                    break;            }        }    }} 


这样我们就解决了在两人进入新的阶段后,无需修改main方法中的代码.

 

那么如果这时两人已经到了谈婚论嫁的时候,该怎么办呢?也就是要再新加入一个阶段叫做结婚呢?

 

 

 

引入策略模式

 

普通的办法还是要去新增方法,再修改调用代码,那我们有没有别的办法呢?别着急,先看看策略模式的定义:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户.

 

策略模式类图如下:

 

 

那么使用策略模式改装,我们上面场景的类图如下:

 

 

模式出了类型那么我们写代码当然就不难了.

 

首先呢,我们需要抽象出来追女孩策略,这个策略里面有一个公共的接口就是去做(也就是行动的意义).例如:送礼物,吃饭,浪漫,都是需要人去做去行动的.

 

案例如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace 策略模式{    //追女孩策略抽象类     public abstract class PursueaGirlStrategy    {        //追女孩策略中都有一个统一的接口,就是行动        public abstract void JustDoIt();    }    //接下来,就是追女孩策略中,各个环节策略的实现啦,代码如下:    //第一阶段 送小礼物    public class SendGiftStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("送给女方精美小礼物!");        }    }     //第二阶段 请客吃饭    public class EatStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("请女生吃牛排!");        }    }        //第三阶段 浪漫:烛光晚餐等待女友    public class RomanticStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("精心制作了红酒、晚餐与蜡烛,等待女友回家!");        }    }     //最后就是,承接策略实例,提供统一调用的策略上下文了,代码如下     public class PursueaGirlContext    {        PursueaGirlStrategy strategy;         public PursueaGirlContext(PursueaGirlStrategy strategy)        {            this.strategy = strategy;        }         //调用策略的公共接口方法         public void ContextJustDoIt()        {            if (this.strategy!=null)            {                this.strategy.JustDoIt();            }        }    }    class Program    {                   static void Main(string[] args)        {           //定义追女孩策略上下文对象             PursueaGirlContext context = null;             Console.WriteLine("现在是第几阶段?");             string level = Console.ReadLine();            switch (level)            {                case "one"://第一阶段                     context = new PursueaGirlContext(new SendGiftStrategy());                    break;                case "two"://第二阶段                    context = new PursueaGirlContext(new EatStrategy());                    break;                case "three": //第三阶段                    context = new PursueaGirlContext(new RomanticStrategy());                    break;                default:                    Console.WriteLine("没这个打算凑什么热闹?");                    break;            }             //统一的策略调用模式             context.ContextJustDoIt();         }    }} 


好的,策略模式与我们的场景先告一段落,这个时候可能有人会问,策略模式和工厂模式很像啊,都是提供一个统一的接口,用不同的实例去实例化,那么我们来看看策略模式与工厂模式的区别吧.

 

 

 

策略模式与工厂模式的区别
 

概念上理解:

(1)策略模式:是告诉上下文,我需要去做什么,至于使用怎么实现,需要上下文去使用当前对应的策略去实现.例如:项目经理(客户端):”我要实现即时消息功能”,那么我们程序员(上下文)就需要去寻找对应的策略(开发即时消息模块的策略)去实现.

 

(2)工厂模式:告诉工厂,此时我需要什么部件你去给我制造,例如:开发即时消息模块,我需要JS的弹出框,我就会告诉UI(工厂),给我做一个JS弹出框,要求模仿EXT.

 

 

 

策略与工厂

了解了他们的区别之后,我们再来看上面策略模式实现的一个问题,例如:需要加入结婚策略时,还是需要增加结婚策略类,并且修改客户端(main方法)中的调用代码.那么我们把提供使用策略的代码放到工厂中呢?这样我们以后就只需增加新策略修改工厂就行了,客户端不需要修改.

 

我们使用工厂之后的代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace 策略模式{    //追女孩策略抽象类     public abstract class PursueaGirlStrategy    {        //追女孩策略中都有一个统一的接口,就是行动        public abstract void Justdoit();    }    //接下来,就是追女孩策略中,各个环节策略的实现啦,代码如下:    //第一阶段 送小礼物    public class SendGiftStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("送给女方精美小礼物!");        }    }     //第二阶段 请客吃饭    public class EatStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("请女生吃牛排!");        }    }        //第三阶段 浪漫:烛光晚餐等待女友    public class RomanticStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("精心制作了红酒、晚餐与蜡烛,等待女友回家!");        }    }     //添加第四阶段 结婚    public class MarriedStrategy : PursueaGirlStrategy    {        public override void Justdoit()        {            Console.WriteLine("两人民政局领证!");        }    }     //策略的宿主 承载当前需要执行的策略    public class PursueaGirlContext    {        PursueaGirlStrategy staregy;        public PursueaGirlContext(PursueaGirlStrategy strategy)        {            this.staregy = strategy;        }         //调用策略的公共接口方法        public void ContextJustdoit()        {            if (this.staregy != null)            {                this.staregy.Justdoit();            }        }     }     //提供策略的工厂    public class FactoryStrategy    {        //根据客户端参数创建策略        public static PursueaGirlContext GetStrategy(string level)        {            //定义追女孩策略上下文对象            PursueaGirlContext context = null;            switch (level)            {                case "one"://第一阶段  礼物                    context = new PursueaGirlContext(new SendGiftStrategy());                    break;                case "two"://第二阶段 吃饭                    context = new PursueaGirlContext(new EatStrategy());                    break;                case "three": //第三阶段 浪漫                    context = new PursueaGirlContext(new RomanticStrategy());                    break;                case "four"://第四阶段 结婚                    context = new PursueaGirlContext(new MarriedStrategy());                    break;                default:                    context = null;                    break;            }            return context;        }    }     class Program    {                   static void Main(string[] args)        {            Console.Write("现在是第几阶段?:");            string level = Console.ReadLine(); //代表当前是哪个阶段             //定义追女孩策略上下文对象            PursueaGirlContext context = FactoryStrategy.GetStrategy(level);             //统一的策略调用模式            context.ContextJustdoit();         }    }} 


这样,我们以后如果有新的策略只需要增加新的策略类,修改工厂即可,那么肯定有同学会问,这样只不过是把修改客户端移动到工厂里面了,将来还是需要工厂,没办法彻底解决调用修改的,怎么办?别着急,以后慢慢学.先掌握这种思想.

3 0
原创粉丝点击