设计模式笔记——策略模式(Strategy Pattern)

一、概述

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

--摘自《Head First设计模式》

二、策略模式:

我们用《Head First设计模式》一书中的例子分析一下为什么我们采用策略模式解决问题。

现在我们要开发一个鸭子的游戏,开始鸭子有游泳,叫,玩等行为。

我们用继承和多态来实现不同的鸭子执行不同的行为,在我们遇到一个问题,每增加一个类型的鸭子我们都需要重写类型内部发方法,最后发现很多重复代码。

这时,你的老板不高兴了,需要你做优化处理,首先我们考虑到接口:

但是接口实现过程中同样有过多的重复代码出现,没有从根本上解决代码堆积的问题。

这时策略模式就派上用场了,看一下类图:

 

 显而易见,我们把可变的行为以接口继承的方式实现,行为接口与Duck类以组合形式存在。

 

三. 源码实现:

1. 飞行行为:

    public interface FlyBehavior
    {
        string Fly();
    }

    public class FlyWithWing:FlyBehavior
    {
        public string Fly()
        {
            return string.Format("I am flying!");
        }
    }

    public class FlyNoWay:FlyBehavior
    {
        public string Fly() 
        {
            return string.Format("I Can't fly!");
        }
    }

    public class FlyRocketPowered:FlyBehavior
    {
        public string Fly()
        {
            return string.Format("I'm flying with a rocket!");
        }
    }

2. 鸭叫行为:

    public interface QuackBehavior
    {
        string quack();
    }

    public class Quack:QuackBehavior
    {
        public string quack()
        {
            return string.Format("Quack!");
        }
    }

    public class SQuack:QuackBehavior
    {
        public string quack()
        {
            return string.Format("SQuack!");
        }
    }

    public class MuteQuack:QuackBehavior
    {
        public string quack()
        {
            return string.Format("MuteQuack!");
        }
    }


3. 鸭子基类:

public abstract class Duck
{
    protected FlyBehavior flyBehavior;
    protected QuackBehavior quackBehavior;

    public abstract string Display();

    public string PerformFly()
    {
        return flyBehavior.Fly();
    }

    public string PerformQuack()
    {
        return quackBehavior.quack();
    }

    public void SetFlyBehavior(FlyBehavior flyBehavior)
    {
        this.flyBehavior = flyBehavior;
    }

    public void SetQuackBehavior(QuackBehavior quackBehavior)
    {
        this.quackBehavior = quackBehavior;
    }

    public string Swim()
    {
        return string.Format("I'm Swimming!");
    }
}

4.鸭子子类:

public class MallardDuck:Duck
{
    public MallardDuck()
    {
        flyBehavior = new FlyWithWing();
        quackBehavior = new Quack();
    }
    public override string Display()
    {
        return string.Format("I'm a real duck!");
    }
}

public class ModelDuck:Duck
{
    public ModelDuck()
    {
        flyBehavior = new FlyNoWay();
        quackBehavior = new MuteQuack();
    }
    public override string Display()
    {
        return string.Format("I'm a model duck!");
    }
}

5.测试实现:

[TestClass]
public class MallardDuckTest
{
    [TestMethod]
    public void MallardDuckBehavior()
    {
        string expected = "Quack!";
        Duck mallardDuck = new MallardDuck();
        string actual= mallardDuck.PerformQuack();
        Assert.AreEqual(expected,actual);

        expected = "I am flying!";
        actual = mallardDuck.PerformFly();
        Assert.AreEqual(expected, actual);

        expected = "I'm flying with a rocket!";
        mallardDuck.SetFlyBehavior(new FlyRocketPowered());
        actual = mallardDuck.PerformFly();
        Assert.AreEqual(expected, actual);
    }
}

四. 总结

我们用策略模式解决了那些问题:

1.代码在子类中的重复问题。

2.运行时行为不容易改变。

3.很难知道所有鸭子的行为。

4. 改变会牵一发而东全身,造成其他鸭子不想要的改变问题。

我们回顾一下OO的重要原则:

1. 封装变化。

2. 多用组合,少用继承。

3. 针对接口编程,不针对实现编程。

 

原文地址:https://www.cnblogs.com/Abel-Zhang/p/StrategyPattern.html