它是如何工作的,它的用途是什么,什么时候应该使用它?
6 回答
让我们以简单的方式解释策略模式:
您有一个Car()
带有 method的类run()
,因此您可以在伪语言中以这种方式使用它:
mycar = new Car()
mycar.run()
现在,您可能希望run()
在程序执行时动态更改行为。例如,您可能想要模拟电机故障或在视频游戏中使用“增强”按钮。
有几种方法可以进行这种模拟:使用条件语句和标志变量是一种方法。策略模式是另一种模式:它将方法的行为委托run()
给另一个类:
Class Car()
{
this.motor = new Motor(this)
// passing "this" is important for the motor so it knows what it is running
method run()
{
this.motor.run()
}
method changeMotor(motor)
{
this.motor = motor
}
}
如果你想改变汽车的行为,你可以改变电机。(在程序中比在现实生活中更容易,对吧?;-))
如果您有很多复杂的状态,这将非常有用:您可以更轻松地更改和维护它们。
问题
策略模式用于解决可能(或预计它们可能)由不同策略实现或解决的问题,并为此类情况提供明确定义的接口。每个策略本身都是完全有效的,其中一些策略在某些情况下更可取,允许应用程序在运行时在它们之间切换。
代码示例
namespace StrategyPatterns
{
// Interface definition for a Sort algorithm
public interface ISort
{
void Sort(List<string> list)
}
// QuickSort implementation
public class CQuickSorter : ISort
{
void Sort(List<string> list)
{
// Here will be the actual implementation
}
}
// BubbleSort implementation
public class CBubbleSort : ISort
{
void Sort(List<string> list)
{
// The actual implementation of the sort
}
}
// MergeSort implementation
public class CMergeSort : ISort
{
void Sort(List<string> list)
{
// Again the real implementation comes here
}
}
public class Context
{
private ISort sorter;
public Context(ISort sorter)
{
// We pass to the context the strategy to use
this.sorter = sorter;
}
public ISort Sorter
{
get{return sorter;)
}
}
public class MainClass
{
static void Main()
{
List<string> myList = new List<string>();
myList.Add("Hello world");
myList.Add("Another item");
myList.Add("Item item");
Context cn = new Context(new CQuickSorter());
// Sort using the QuickSort strategy
cn.Sorter.Sort(myList);
myList.Add("This one goes for the mergesort");
cn = new Context(new CMergeSort());
// Sort using the merge sort strategy
cn.Sorter.Sort(myList);
}
}
}
- 什么是策略?战略是旨在实现特定目标的行动计划;
- “定义一系列算法,封装每个算法,并使它们可互换。策略让算法独立于使用它的客户而变化。” (四人组);
- 指定一组类,每个类代表一个潜在的行为。在这些类之间切换会改变应用程序的行为。(战略);
- 可以在运行时(使用多态性)或设计时选择此行为;
- 捕获接口中的抽象,将实现细节隐藏在派生类中;
- 策略的替代方法是通过使用条件逻辑来更改应用程序行为。(坏的);
使用此模式可以更轻松地添加或删除特定行为,而无需重新编码和重新测试应用程序的全部或部分;
良好的用途:
- 当我们有一组相似的算法并且它需要在应用程序的不同部分在它们之间进行切换时。使用策略模式可以避免ifs并简化维护;
- 当我们想向超类添加不一定对每个子类都有意义的新方法时。我们不是以传统方式使用接口,而是添加新方法,而是使用一个实例变量,它是新功能接口的子类。这被称为组合:类不是通过继承来继承能力,而是由具有正确能力的对象组成;
一个密切相关的模式是委托模式。在这两种情况下,一些工作都会传递给其他一些组件。如果我理解正确,这些模式之间的区别是这样的(如果我错了,请纠正我):
在委托模式中,委托由封闭(委托)类实例化;这允许通过组合而不是继承来重用代码。封闭类可能知道委托的具体类型,例如,如果它自己调用其构造函数(而不是使用工厂)。
在策略模式中,执行策略的组件是通过其构造函数或设置器(根据您的宗教信仰)提供给封闭(使用)组件的依赖项。using 组件完全不知道正在使用什么策略;该策略始终通过接口调用。
有人知道其他区别吗?
直接来自Strategy Pattern Wikipedia 文章:
策略模式对于需要动态交换应用程序中使用的算法的情况很有用。策略模式旨在提供一种方法来定义一系列算法,将每个算法封装为一个对象,并使它们可互换。策略模式让算法独立于使用它们的客户端而变化。
补充一下已经很精彩的答案:策略模式与将一个(或多个函数)传递给另一个函数非常相似。在策略中,这是通过将所述函数包装在一个对象中,然后传递该对象来完成的。有些语言可以直接传递函数,所以它们根本不需要模式。但是其他语言不能传递函数,但是可以传递对象;然后应用该模式。
尤其是在类 Java 语言中,您会发现该语言的类型动物园非常小,并且您扩展它的唯一方法是创建对象。因此,大多数问题的解决方案是提出一个模式;一种组合对象以实现特定目标的方法。具有更丰富类型动物园的语言通常有更简单的解决问题的方法——但更丰富的类型也意味着你必须花更多的时间来学习类型系统。具有动态类型规则的语言通常也会偷偷摸摸地解决问题。