模式一:策略模式

      

1、 模式一:策略模式

 

1.1策略模式定义:

策略模式定义了算法簇,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

 

1.2应用场景

    现任举一现实案例如下,以此来模拟软件开发中的问题事实。

Human类如下:public class Human

{

                  public void Eat()

{

  Console.Write(“吃饭”);

};  

                      public void Drink();

{

  Console.Write(“喝水”);

}

}

现实世界中任何一个具体的人都继承于该Human类。现假设出现了会游泳的人,一种常见的做法是在父类中加入Swin()方法。很明显,这么做会因为继承带来问题,因为并不是所有人都会游泳。而且即使所有人都会游泳,每个人游泳的方式也不尽相同。当然,这里每个人游泳方式的不同可以用多态(方式可采用虚方法或接口实现)来解决,但如果A,B2人恰巧都采用同一种游泳方式,则多态无法解决AB之间代码重用问题。那么,如何用一种方法同时解决继承和多态所带来的问题,这个时候,我们可以用策略模式来解决。

 

1.3策略模式分析与实现(C#描述)

          对上述问题进行分析,我们发现:Swin()是一种动作,而且是一种变化的动作。根据策略模式定义,策略模式是对一系列算法的封装,算法此处恰好意味着动作,即对一系列动作的封装。每个人游泳的动作可能不同,这里的算法簇集合就是游泳动作的集合。另外,OO原则告诉我们,应该尽量找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混合在一起。对应到该例:Swin()不像Eat()Drink()(每个人都一定会吃饭和喝水),是一个变化的因素,所以这里,我们将Swin个这动作从父类中抽取出来,并定义一个单独的Swin接口:

public interface ISwinBehavior

    {

        void Swin();

   }

   然后每一种具体的Swin动作作为一个单独的类实现该接口。

   例如蛙泳定义为:public class FrogSwin : ISwinBehavior

     {

                     public viod Swin()

         {            

                      Console.WriteLine("蛙泳");

        }

   }

   对应于策略一。

  

   蝶泳定义为:public class ButterflySwin:ISwinBehavior

    {

                public viod Swin()

        {

                  Console.WriteLine("蝶泳");

        }

  }

   对应于策略二。

 

   这里之所以把Swin个这动作从父类中抽离出一个接口,然后具体的动作类实现该接口,而不是直接抽离成一个个具体的类。原因为根据上述OO原则,我们应该尽量针对接口编程,则不是针对具体实现,这里如果抽离成的一个个具体的类,实际上就是一个个具体的实现。那么为什么要针对接口而不是实现编程,一会再具体描述。下面继续策略模式,动作被抽离成策略并定义好实现形态后,我们改变父类的定义如下:

    //客户父类

    public class Human

    {

        public ISwinBehavior ISwin;

//以组合的方式定义接口,符合面向对象原则,多用组合,少用继承。

 

        public void Eat()

        {

            Console.WriteLine("吃饭");

        }

 

        public void Drink()

        {

            Console.WriteLine("喝水");

        }

 

        public void Swin()

        {

            ISwin.Swin();

        }

 }

 

 

   子类定义如下:

    //客户子类

    public class XiaoMing : Human

    {

        public XiaoMing()

        {

            this.ISwin = new FrogSwin();

        }

 

        public void ChangeSwinBehavior()

        {

            this.ISwin = new ButterflySwin();

        }

    }

 

  调用代码如下:

//调用类

    public class Strategy_Test

    {

        public static void Do()

        {

            XiaoMing lobj_XiaoMing = new XiaoMing();

            lobj_XiaoMing.Swin();//输出蛙泳

            lobj_XiaoMing.ChangeSwinBehavior();

            lobj_XiaoMing.Swin();//输出蝶泳

        }

    }

 

 至此,策略模式完毕。

 

 通过策略模式,解决了上述继承和多态所引发的问题。首先关于继承的问题:父类中只包含游泳这一行为接口,而不是具体实现,这样子类并未依赖于父类的具体实现,这样就避免了如果在父类中写入实现子类却不会游泳的问题,策略模式中如果不会游泳,只需在子类构造函数中将接口赋以不会游泳的实现类(即不会游泳策略)即可。其次关于多态不能重用代码的问题:由于策略被抽离成不同的实现类。这样如果AB 均会蛙泳,则只需在AB的构造函数中给接口赋以相同的策略,而策略类本身实现了在不同的子类中重用。而实际上,该策略类将不只可以用于HUMAN类,而是可以用于任何有Swin形为的类,即策略可以跨类重用。

  

   上面讲了OO原则应该尽量针对接口而不是实现编程,那么这里分析一下为什么要针对接口而不是实现编程。本人认为:接口代表的是一种不变,而具体实现代表变化,接口是就用来解决软件开发中的变化对程序带来的负面影响(可维护性差)的一种软件领域的工具。我们都知道,在软件开发领域,唯一不变的就是变化本身。举一个软件开发中的实例,在财务软件开发中,算工资这个动作是不变的,而具体根据什么公式算却是经常变化的。那么算工资这个动作可以理解成接口,而怎么算则是具体实现。在软件开发过程中,如果我要算工资,那么算工资的调用者所做的只是调用算工资这个接口,至于该接口的实现类是根据什么公式计算工资的,调用者并不需要知道,一旦工资计算方式发生变化时,我们所做的只需改变接口的实现类,而调用者(客户)是不要做任何改动的。如果现实世界算工资都是从来没有变化的,那么我们根本不需用到接口,直接调用实现类就行了。另外,通过接口还可以在运行期间动态改变类的行为方式。一如上例:我们可以在运行时态动态改变XiaoMing的游泳方式,将其本身为蝶泳的方式改为蛙泳。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值