zoukankan      html  css  js  c++  java
  • Strategy 策略模式

    策略模式:定义一系列的算法,把他们一个个封装起来,并且使它们可以相互替换,。本模式使得算法可以独立于使用它的客户而变化。

    故事背景:开发一款鸭子模拟游戏,游戏中会出现各种鸭子,一边游泳,一边嘎嘎叫。此系统的内部使用了标准的OO技术,设计了一个鸭子基类,并让各种鸭子继承此基类。基类中有Speak()方法,Swim()方法,还有一个虚方法Display()。3个子类WhiteDuck,BlackDuck,RubberDuck

    代码如下:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace StrategyPattern
     8 {
     9    public  class Duck
    10     {
    11         protected string name = "duck";
    12         public Duck()
    13         {
    14 
    15         }
    16         public Duck(string name)
    17         {
    18             this.name = name;
    19         }
    20         public void Quack()
    21         {
    22             Console.WriteLine(name + "鸭子在嘎嘎叫");
    23         }
    24         public void Swim()
    25         {
    26             Console.WriteLine(name + "鸭子在游泳");
    27         }
    28 
    29         public virtual void Display()
    30         {
    31             Console.WriteLine(name + "基类的display方法被调用");
    32         }
    33         public void Fly()
    34         {
    35             Console.WriteLine(name + "鸭子在飞");
    36         }
    37     }
    38 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace StrategyPattern
     8 {
     9     class RedDuck :Duck
    10     {
    11         public RedDuck()
    12         {
    13 
    14         }
    15         public RedDuck(string name):base(name)
    16         {
    17 
    18         }
    19         public override void Display()
    20         {
    21          
    22             Console.WriteLine(name + "红头鸭子");
    23         }
    24     }
    25 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace StrategyPattern
     8 {
     9     class GreenDuck:Duck
    10     {
    11         public GreenDuck()
    12         {
    13 
    14         }
    15         public GreenDuck(string name):base(name)
    16         {
    17 
    18         }
    19         public override void Display()
    20         {
    21             Console.WriteLine(name + "绿头鸭子");
    22         }
    23     }
    24 }
    using System;
    
    namespace StrategyPattern
    {
        class RubberDuck:Duck
        {
            public RubberDuck()
            {
    
            }
            public RubberDuck(string name):base(name)
            {
                
            }
    
            public override void Display()
            {
                Console.WriteLine(name + "橡皮鸭子");
            }
    
        }
    }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace StrategyPattern
     8 {
     9     class Client
    10     {
    11         static void Main(string[] args)
    12         {
    13             Duck redDuck = new RedDuck("Mr.Red");
    14             redDuck.Display();
    15             redDuck.Quack();
    16             redDuck.Swim();
    17 
    18             Duck greenDuck = new GreenDuck("Mr.Green");
    19             greenDuck.Display();
    20             greenDuck.Quack();
    21             greenDuck.Swim();
    22 
    23             Duck rubberDuck = new RubberDuck("Mr.Rubber");
    24             rubberDuck.Display();
    25             rubberDuck.Quack();
    26             rubberDuck.Swim();
    27 
    28             Console.ReadKey();
    29         }
    30     }
    31 }

    运行结果:

    新的需求:现在需要会飞的鸭子

    实现:只要在基类中新加一个Fly()方法,然后在客户端调用就可以了。真的是这样么?如果这样做,你会RubberDuck在飞(注:rubber 橡皮),这可不是我们想要的结果。

    要想解决这个办法很简单,在RubberDuck中定义一个同名函数隐藏基类中的同名方法Fly,然后什么都不做就行了。或者把Fly设计成一个虚方法,同样在子类中覆盖,什么都不做就行了。

    新的需求:需要诱饵鸭子,既不会飞,也不会叫。解决这个问题的方法也很简单,在定义一个子类DecoyDuck,覆盖子类的Fly和Speak方法就行了,同样方法体为空。

    思考:利用继承来提供Duck的行为导致的缺点:

    1.运行时的行为不容易改变

    2.改变会牵一发而动全身,造成其他鸭子不想要的改变。

    3.代码在多个子类中重复

    4.很难直到所有鸭子的全部行为。

    策略模式大显身手:

    把行为与Duck分离出来,定义两个接口QuackBehaviour和FlyBehaviour。定义两个实现QuackBehaviour的类:QuackLoudly和QuackMute。定义两个实现FlyB ehaviour的类:FlyWithWings和FlyNoway。

    Duck中删除Fly和Quack方法,添加PerformQuack和PerformFly方法。要想获得叫和飞的行为只要获得飞和叫的类就可以了,让飞和叫的类取实现这些功能。因此需要在Duck中添加两个接口的引用:

    QuackBehaviour quackBehaviour 和 FlyBehaviour flyBehaviour。获得引用还不行,还需要获得实例。因此再添加2个方法:SetQuackBehaviour(QuackBehaviour qb) 和 SetFlyBehaviour(FlyBehaviour fb);

    具体代码如下,2个具体的鸭子类就可已说明问题了,偷懒起见GreenDuck就不测试了。

     1 using System;
     2 namespace StrategyPattern
     3 {
     4     public interface FlyBehaviour
     5     {
     6          void Fly();
     7     }
     8     public class FlyWithWings : FlyBehaviour
     9     {
    10        public void Fly()
    11         {
    12             Console.WriteLine("我会飞");
    13         }
    14     }
    15     public class FlyNoWay:FlyBehaviour
    16     {
    17         public void Fly()
    18         {
    19             Console.WriteLine("我不会飞");
    20         }
    21     }
    22 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace StrategyPattern
     8 {
     9     public interface QuackBehaviour
    10     {
    11         void Quack();
    12     }
    13 
    14     public class QuackLoudly:QuackBehaviour
    15     {
    16         public void Quack()
    17         {
    18             Console.WriteLine(("嘎嘎叫"));
    19         }
    20     }
    21     public class QuackMute:QuackBehaviour
    22     {
    23         public void Quack()
    24         {
    25             Console.WriteLine("不会叫");
    26         }
    27            
    28     }
    29 }
     1 using System;
     2 
     3 namespace StrategyPattern
     4 {
     5     public  class Duck
     6     {
     7         public FlyBehaviour flyBehaviour;
     8         public QuackBehaviour quackBehaviour;
     9         protected string name = "duck";
    10         public Duck()
    11         {
    12 
    13         }
    14         public Duck(string name)
    15         {
    16             this.name = name;
    17         }
    18         public void SetFlyBehaviuor(FlyBehaviour fb)
    19         {
    20             flyBehaviour = fb;
    21         }
    22         public void SetQuackBehaviour(QuackBehaviour qb)
    23         {
    24             quackBehaviour = qb;
    25         }
    26        
    27         public void Swim()
    28         {
    29             Console.WriteLine(name + "鸭子在游泳");
    30         }
    31         public void PerformQuack()
    32         {
    33             Console.WriteLine(("I am" + name));
    34             quackBehaviour.Quack();
    35         }
    36         public virtual void Display()
    37         {
    38             Console.WriteLine(name + "基类的display方法被调用");
    39         }
    40        public  void PerformFly()
    41         {
    42             Console.WriteLine(("I am" + name));
    43             flyBehaviour.Fly();
    44         }
    45     }
    46 }

    测试类Client.

     1 using System;
     2 
     3 namespace StrategyPattern
     4 {
     5     class Client
     6     {
     7         static void Main(string[] args)
     8         {
     9             FlyBehaviour flyBehaviour = new FlyWithWings();         //定义一个会飞的行为
    10             FlyBehaviour notFlyBehaviour = new FlyNoWay();          //定义一个不会飞的行为
    11             QuackBehaviour quackBehaviour = new QuackLoudly();      //定义一个嘎嘎叫的行为
    12             QuackBehaviour notQuackBehaviour = new QuackMute();     //定义以一个不会叫的行为
    13 
    14             Duck redDuck = new RedDuck("Mr.Red");
    15             redDuck.SetFlyBehaviuor(flyBehaviour);                  //动态添加飞行行为
    16             redDuck.PerformFly();
    17             redDuck.SetQuackBehaviour(quackBehaviour);                  //动态添加嘎嘎叫行为
    18             redDuck.PerformQuack();
    19 
    20            
    21 
    22             Duck rubberDuck = new RubberDuck("Mr.Rubber");
    23             rubberDuck.SetFlyBehaviuor(notFlyBehaviour);
    24             rubberDuck.PerformFly();
    25             rubberDuck.SetQuackBehaviour(notQuackBehaviour);
    26             rubberDuck.PerformQuack();
    27 
    28             Console.ReadKey();
    29         }
    30     }
    31 }

    参考资料:《Head First 设计模式》

  • 相关阅读:
    爬虫header和cookie
    爬虫代理squid
    response对象
    pyspider中内容选择器常用方法汇总
    非阻塞 sleep
    post请求体过大导致ngx.req.get_post_args()取不到参数体的问题
    常用lua代码块
    nginx静态文件缓存的解决方案
    lua-resty-gearman模块
    非在线PDF转图片!!!
  • 原文地址:https://www.cnblogs.com/blackteeth/p/10206489.html
Copyright © 2011-2022 走看看