设计模式-策略模式
定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
策略模式的使用场景
(1) 多个类之区别在表现行为不同,在运行时选择具体要执行的行为
(2) 需要在不同的情况下使用不同的策略
(3) 对客户隐藏具体策略的实现细节,彼此独立
策略模式类图如下
Context 封装角色
屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化
Strategy 抽象策略角色
策略、算法的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
ConcreteStrategy 具体策略角色
实现抽象策略规定的方法和属性
实例
周末要放松下,去干什么呢??? 可以选择 骑行、烧烤、踏青、逛公园 等,这些休闲娱乐方式每一种都是一个策略。
无论选择哪种方式,都要喊上几个朋友一起 需要有一个喊朋友的功能,出门前准备, 至少还需要一个娱乐的功能。
代码如下
Strategy 抽象策略角色
// 抽象策略
public interface IStrategy
{
// 邀请朋友
void InviteFriends();
// 出门准备
void Prepare();
// 玩耍
void Play();
}
ConcreteStrategy 具体策略角色
// 骑行策略
public class RidingStrategy : IStrategy
{
// 邀请朋友
public void InviteFriends()
{
Console.WriteLine("叫上喜欢骑行的朋友们");
}
// 出门准备
public void Prepare()
{
Console.WriteLine("搜索一条骑行路线");
Console.WriteLine("找找骑行装备");
}
// 玩耍
public void Play()
{
Console.WriteLine("开始骑行 \n");
}
}
// 户外烧烤策略
public class BBQStrategy : IStrategy
{
// 邀请朋友
public void InviteFriends()
{
Console.WriteLine("喜欢烧烤的朋友们来吧");
}
// 出门准备
public void Prepare()
{
Console.WriteLine("查查哪里允许烧烤");
Console.WriteLine("买羊肉、牛肉、鸡翅等、烧烤炉、烧烤碳");
}
// 玩耍
public void Play()
{
Console.WriteLine("开始烧烤啦 \n");
}
}
Context 封装角色
public class Human
{
private IStrategy _strategy;
public Human()
{
}
// 设置具体策略角色
public void SetStrategy(IStrategy strategy)
{
_strategy = strategy;
}
// 周末玩耍
public void WeekendPlay()
{
// 调用策略角色方法
_strategy.InviteFriends();
_strategy.Prepare();
_strategy.Play();
}
}
代码调用如下
public class Client
{
public Client()
{
Human human = new Human();
// 骑行策略
RidingStrategy ridingStrategy = new RidingStrategy();
// 将骑行策略赋值给 human
human.SetStrategy(ridingStrategy);
human.WeekendPlay();
// 野外烧烤策略
BBQStrategy bBQStrategy = new BBQStrategy();
// 将骑行策略赋值给 human
human.SetStrategy(bBQStrategy);
human.WeekendPlay();
}
}
运行结果如下
优点:
(1) 算法可以自由切换
(2) 避免使用功能多重条件判断(如果不使用策略模式我们可能会使用 if … else switch 等条件语句不利于维护)
(3) 扩展性好,增加一个策略只需要实现接口即可
缺点:
(1) 策略类数量会增多,每个策略都是一个类,复用的可能小
(2) 所有的策略类都需要对外暴露