策略模式如何工作?
它是如何工作的,用途是什么,何时应使用它?
解决方案
直接来自Strategy Pattern Wikipedia文章:
The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used in an application. The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them.
让我们以简单的方式来说明策略模式:
我们有一个带有运行方法run()的类Car(),因此可以在伪语言中使用它:
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); } } }
密切相关的模式是"委托"模式。在这两种情况下,某些工作都会传递给其他组件。如果我理解正确,则这些模式之间的区别是这样(如果我错了,请纠正我):
- 在Delegate模式中,委托是通过封闭(委托)类实例化的;这允许通过组合而不是继承来重用代码。封闭的类可能知道委托人的具体类型,例如如果它本身调用其构造函数(而不是使用工厂)。
- 在策略模式中,执行策略的组件是通过其构造函数或者设置器(根据信仰)提供给封闭(使用)组件的依赖项。使用组件完全不知道正在使用什么策略。该策略始终通过接口调用。
有人知道其他区别吗?
要添加到已经精妙的答案中:策略模式与将一个(或者多个)函数传递给另一个函数有很大的相似性。在该策略中,这是通过将所述函数包装在对象中,然后传递对象来完成的。某些语言可以直接传递函数,因此它们根本不需要模式。但是其他语言不能传递函数,但是可以传递对象。然后适用该模式。
尤其是在类似Java的语言中,我们会发现该语言的类型库非常小,并且扩展它的唯一方法是创建对象。因此,大多数解决问题的方法是提出一种模式。一种组合对象以实现特定目标的方法。具有类型丰富的动物园的语言通常具有解决问题的简单方法-但是类型丰富的语言也意味着我们必须花更多的时间学习类型系统。具有动态类型输入规则的语言通常也可以轻松地解决该问题。