设计模式学习总结-策略模式(Strategy Pattern)
问题:
当我们定义一系列的算法,怎么能使得算法为应对不同的业务需要能自由的动态替换而又不影响到客户端的使用,并且算法的增减、修改都不会影响环境和客户端。
定义:
策略模式定义了一系列算法,把它们一个个封装起来,并且使它们可相互替换。该模式可使得算法能独立于使用它的客户而变化。
意图:
Strategy模式是行为模式,正因为他是一种行为模式,所以他不是用来解决类的实例化的,跟创建什么样的产品没有关系,此模式解决的问题是把一个系列完成相同工作,却实现不同的算法(行为)包装到一系列的策略类里面,使得它们可以相互替换,提供一个访问接口,由客户端决定在什么情况下使用什么具体策略,来完成某一功能。并可以自由的添加修改相应的算法,轻松实现可插入式(Pluggable)的系统的开发。对于客户端来说,不关心实例化了那些对象,生产了那些产品,只需要提供要使用那种策略去完成某一功能。
参与者:
•抽象策略(Strategy)角色:
定义了所支持算法的公共接口,各种不同的算法以不同的方式实现这个接口,Context通过这个接口来调用ConcreteStrategy定义的算法。一般使用接口或抽象类实现。
•具体策略(ConcreteStrategy)角色:
继承抽象策略(Strategy)角色,封装了具体的算法和行为。
•Context:
策略的外部封装类,或者说策略的容器类。它维护了一个对Strategy对象的引用。负责根据不同策略动态设置运行时Strategy具体的ConcreteStrategy,并实现交互和数据传递。
UML图:
实例说明:
诺基亚手机工厂
比如Nokia公司现有中国,芬兰两家生产工厂。在中国生产的是亚太版,在芬兰生产的是欧美版,两个工厂的生产细节可能是不同的,但是都可以生产N8,N9两款手机,并且可以动态的增加手机工厂,如墨西哥工厂生产拉美版的N8,N9.
uml图如下:
代码:
/// 手机工厂抽象策略(Strategy)角色
/// </summary>
public abstract class IPhoneFactory
{
public abstract void CreateN8();
public abstract void CreateN9();
}
/// <summary>
/// 手机工厂具体策略(ConcreteStrategy)角色
/// </summary>
public class PhoneFactory_China : IPhoneFactory
{
public override void CreateN8()
{
System.Console.WriteLine("我是中国生产的N8");
}
public override void CreateN9()
{
System.Console.WriteLine("我是中国生产的N9");
}
}
/// <summary>
/// 手机工厂具体策略(ConcreteStrategy)角色
/// </summary>
public class PhoneFactory_Finland : IPhoneFactory
{
public override void CreateN8()
{
System.Console.WriteLine("我是芬兰生产的N8");
}
public override void CreateN9()
{
System.Console.WriteLine("我是芬兰生产的N9");
}
}
/// <summary>
/// 手机生产Context
/// </summary>
public class PhoneFactoryContext
{
IPhoneFactory phoneFactory = null;
public PhoneFactoryContext(IPhoneFactory _phoneFactory)
{
this.phoneFactory = _phoneFactory;
}
public void CreateN8()
{
phoneFactory.CreateN8();
}
public void CreateN9()
{
phoneFactory.CreateN9();
}
}
/// <summary>
/// 客户端
/// </summary>
void StrategyTest()
{
PhoneFactoryContext context = new PhoneFactoryContext(new PhoneFactory_China());
context.CreateN8();
}
优点:
•策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,并能起到很好的约束作用。
•避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
缺点:
•每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
•客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
应用情景:
•多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
•需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
•对客户隐藏具体策略(算法)的实现细节,彼此完全独立。