定义

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

  • 环境上下文角色(Context):持有一个Stragety类的引用;
  • 抽象策略角色(Stragety):这是一个抽象角色,通常由一个抽象类或接口来实现,此角色给出所有具体策略类要实现的接口方法;
  • 具体策略角色(ConcreateStragety):包装了相关算法和行为

适用场景

1.一些系统需要动态的在各个算法中切换,那么这些算法可以包装到一个个的策略类中,如一些权限控制、计算器类、税收计算场景都可以考虑使用策略模式,方便未来扩展。 2.一个对象有许多行为,如果不适用模式会造成很多if-else判断,就可以抽象出行为到具体的策略类中。

UML 图

stragetyDesignPatten

代码实现

namespace StragetyDesignPattens
{
    public interface ITheme
    {
        string ShowTheme();
    }

    public class DefaultTheme:ITheme
    {
        public string ShowTheme()
        {
            return "Default theme";
        }
    }

    public class BrightTheme:ITheme
    {
        public string ShowTheme()
        {
            return "Bright theme";
        }
    }

    public class ThemeManager
    {
        private ITheme _theme;

        public ThemeManager(ITheme theme)
        {
            this._theme = theme;
        }

        public string ShowTheme()
        {
            return this._theme.ShowTheme();
        }
    }
}

使用策略者模式代码如下:

namespace DesignPattens.Tests
{
    [TestClass]
    public class StragetyPattenTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            ThemeManager manager=new ThemeManager();
            manager.SetTheme(new DefaultTheme());
            Assert.AreEqual("Default theme",manager.ShowTheme());
            manager.SetTheme(new BrightTheme());
            Assert.AreEqual("Bright theme",manager.ShowTheme());
        }
    }
}

当然这里我们修改主题使用了 new BrightTheme(),如果要修改为其他主题就要修改该行代码,我们可以用依赖注入或者将此类配置到Xml中利用反射动态修改主题,因此更换主题也只需要修改配置文件即可。

总结

其实策略不一定命名为 Stragety,Context 不一定叫Context,可以根据实际情况自己命名,如我们的ThemeManager。策略模式充分体现了 开闭原则(对扩展开发,对修改关闭)。