设计模式—策略模式—简单讲解(说讲解还不如是总结)—配套事例

最近在学习设计模式,参考的书是《Head First设计模式》,里边是针对java语言讲解的,但是我是C#,大同小异,所以我的事例是用C#写的。本来打算上传我的代码压缩文件,可是没有找到上传附件的地方,第一次写博客,大家见谅哈。

下面开始讲解:先来个定义

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

是不是看不太懂,其实我学完了也不是太懂我总觉得这些设计模式是先人们充分的利用了类的封装继承多态而已,就像有拼接积木一样,摆弄摆弄就成了另一个设计模式)

首先这本书是一个鸭子游戏为例,鸭子有很多种,他们有相同的外观和行为,也有不同外观和行为。书中举了两个例子,真鸭子和橡皮鸭,真鸭子会飞,橡皮鸭不会飞,真鸭子叫起来是呱呱,橡皮鸭叫起来是吱吱。

写到这大家是不是觉得应该是写一个基类Duck,里边封装一下鸭子们相同的东西,其他不同的就在子类里扩充一下就好了,其实这是一种最原始的方法,但今天既然说设计模式,那肯定得高大上一点啦。

继续,因为鸭子的种类有很多种,但是他们的飞行行为只有两种,会飞和不会飞,如果我们每个子类都去重写,那就浪费了很多代码。再加上叫声的种类,那就更多了,这才两种行为,如果再加上走路,吃饭等等。那我们的程序员就疯了吧。

所以策略模式被研究出来了,所谓“算法族”就是这些鸭子的行为代码,所以我们要按定义说的把他们封装起来。

这个行为的封装就用到了接口,用接口就是因为我只需要定义这里边有什么行为,具体什么行为,你继承之后自己去实现。

public interface FlyBehavior
    {
        void fly();
    }

public class FlyWithWings : FlyBehavior
    {
        public void fly()
        {
            Console.WriteLine("I can fly!");
        }
    }
    public class FlyNoWay : FlyBehavior
    {
        public void fly()
        {
            Console.WriteLine("I can't fly!");
        }
    }

这里写了一个基础的接口FlyBehavior,FlyWithWings和 FlyNoWay 都继承了他,这就属于把行为封装了,然后大家就想了,你把行为封装了,鸭子怎么和行为产生关联啊,这就是策略模式让我很喜欢的地方(我先把叫声的封装贴下边)





   public interface QuackBehavior
    {
        void quack();
    }

    public class Quack : QuackBehavior
    {
        public void quack()
        {
            Console.WriteLine("gua gua!");
        }
    }
    public class Squeak : QuackBehavior
    {
        public void quack()
        {
            Console.WriteLine("zhi zhi!");
        }
    }


下边是让鸭子用这些行为

public abstract class Duck
    {
        public FlyBehavior flyBehavior;
        public QuackBehavior quackBehavior;
        public abstract void display();
        public void SetFlyBehavior(FlyBehavior fb)
        {
            flyBehavior = fb;
        }
        public void SetQuackBehavior(QuackBehavior qb)
        {
            quackBehavior = qb;
        }
        public void performFly()
        {
            flyBehavior.fly();
        }
        public void performQuack()
        {
            quackBehavior.quack();
        }
    }

看到了吗?Duck基类中的flyBehavior,quackBehavior变量是接口类型。performFly()就调用flyBehavior.fly()

意思是,你给flyBehavior变量初始化什么行为,他就执行什么飞行行为。

SetFlyBehavior()用来动态改变飞行行为,如果鸭子残了不能飞了,你就给他动态赋值FlyNoWay,那他以后就不能飞了。定义中的互相替换就是指的这个啦。

接下来我们看一下继承积累Duck并给鸭子初始化行为的代码

public class RealDuck : Duck
    {
        public RealDuck()
        {
            flyBehavior = new FlyWithWings();
            quackBehavior = new Quack();
        }
        public override void display()
        {
            Console.WriteLine("I am a real Duck");
        }
    }

我们定义了一个真鸭子,给他的行为初始化位可以飞,并且呱呱叫。

接下来看一下这鸭子实现的代码吧





            RealDuck realDuck = new RealDuck();
            realDuck.performFly();
            realDuck.performQuack();

输出结果:I can fiy!

gua gua!

接下来我想动态改变他的行为,那么你就可以这么写



            realDuck.SetFlyBehavior(new FlyNoWay());
            realDuck.SetQuackBehavior(new Squeak());
            realDuck.performFly();
            realDuck.performQuack();


输出结果:I can't fiy!

zhi zhi!

总结(书中原话):
1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
2.针对接口编程,不针对实现编程;
3.多用组合,少用继承;

你可能感兴趣的:(设计模式)