定义:Strategy pattern define a family of algorithms, encapsulate each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.(保留原汁原味吧!木有翻译。)
小故事:生活在北京,每天早晨当我骑着自行车走在上班的路上的时候都能看到和我一样行色匆匆的路人,自行车族还是占相当大的比例的,偶尔会有摩托车呼啸着从身边飞过,相当的嚣张。不过摩托车碰到满街的奥迪,宝马之类的就相形见绌了。开车也有抓瞎的时候,比如堵车了,我们自行车族完全可以绕着走或者从车缝里穿过去,基本不会有太多的影响,你们小轿车就得一直等到交通疏散开才可以,有本事你给我也从车缝里挤过去看看。^_^。交通工具一般能和人的职位头衔相对应起来,像我这样一穷二白的ITer大概也只能骑自行车了,稍微有点钱的可以弄个摩托车跑跑,当然一般老板都有自己的私家轿车。本文的例子就是讲老板,项目经理(我假定他们比较有钱,完全可以支付起使用摩托车的费用)和我们普通ITer选择自己的交通工具去上班。当然老板完全可以也骑自行车,这是合法的也是可行的。
VS自动生成的类图:


实例代码:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Diagnostics;
5
6
namespace StrategyDemo
7

{
8
/**//// <summary>
9
/// Base class for Boss, TeamMember and PM (let's call them workers).
10
/// </summary>
11
public abstract class Worker
12
{
13
protected IVehicle _vehicle;
14
15
//Base class may provide a lot of fields that subclass can inherit.
16
protected string m_Name;
17
18
public string Name
19
{
20
get
{ return m_Name; }
21
set
{ m_Name = value; }
22
}
23
24
/**//// <summary>
25
/// The behavior may quite differnt based on different vehicles,
26
/// so encapsulate into classes that implement IVehicle.
27
/// </summary>
28
public void GoToWork()
29
{
30
Debug.Assert(null != _vehicle, "Please choose your vehicle before you go to work!");
31
_vehicle.Go();
32
}
33
34
/**//// <summary>
35
/// Choose your own vehicle.
36
/// </summary>
37
/// <param name="vehicle"></param>
38
public void SetVehicle(IVehicle vehicle)
39
{
40
_vehicle = vehicle;
41
}
42
43
}
44
45
subclasses of Worker#region subclasses of Worker
46
public sealed class Boss : Worker
47
{
48
public Boss()
49
{
50
Console.WriteLine("I'm a boss!");
51
}
52
public Boss(string name)
53
{
54
m_Name = name;
55
Console.WriteLine("My name is {0}, a boss!", m_Name);
56
}
57
}
58
59
60
public sealed class TeamMember : Worker
61
{
62
public TeamMember()
63
{
64
Console.WriteLine("I am just a team member,having no money.");
65
}
66
}
67
68
69
public sealed class PM : Worker
70
{
71
public PM()
72
{
73
Console.WriteLine("I am a project manager, but I have no my own car!");
74
}
75
}
76
#endregion
77
78
79
/**//// <summary>
80
/// Every vehicle has to implement this interface.
81
/// Notice that every differnt vehicle has its own behavior.
82
/// </summary>
83
public interface IVehicle
84
{
85
void Go();
86
}
87
88
Vehicles that implement IVehicle#region Vehicles that implement IVehicle
89
public sealed class MiniBike : IVehicle
90
{
91
public void Go()
92
{
93
Console.WriteLine("Hey, look at my minibike, it is especially for girls!");
94
}
95
}
96
public sealed class MotorMike : IVehicle
97
{
98
public void Go()
99
{
100
Console.WriteLine("I have a long distance to cover, motorbike can satisfy me!");
101
}
102
}
103
104
public sealed class Car : IVehicle
105
{
106
public void Go()
107
{
108
Console.WriteLine("I'm a millionaire, car is my daily vehicle!");
109
}
110
}
111
#endregion
112
113
114
class Program
115
{
116
static void Main(string[] args)
117
{
118
Boss boss = new Boss("someone");
119
boss.SetVehicle(new Car());
120
boss.GoToWork();
121
Console.WriteLine("**********************************************************");
122
TeamMember teamMember = new TeamMember();
123
teamMember.SetVehicle(new MiniBike());
124
teamMember.GoToWork();
125
Console.WriteLine("**********************************************************");
126
PM pm = new PM();
127
pm.SetVehicle(new MotorMike());
128
pm.GoToWork();
129
130
Console.ReadKey();
131
}
132
}
133
}
134
运行结果图:

本例引出的面向对象原则:
封装变化的部分(Encapsulate what varies).
本例中不同的人使用不同的交通工具,操作可能不尽相同,开车和骑摩托车肯定不一样,骑自行车和骑摩托车也不会一样,至少骑摩托车不用使劲去蹬,交通工具可能只适用用特定的人群,像我就不会开车。这部分是变化的,所以可以从类中抽取出来单独放到一个类中,注意这个类只封装了一一些操作,并不一定有成员变量。
优先选择组合而不是继承(Favor composition over inheritance)。
对于本例来说显然在work类中添加GoToWork的实现代码让子类使用是不合适的,因为不同的人到公司上班的方式是不一样的。在work中实现一个抽象类供子类override是不是可以呢?只能解决一部分问题,如果打算运行是改变行为呢?对于本例来说加入一天老板突然想骑自行车上班怎么办?
Boss boss = new Boss("someone");
boss.SetVehicle(new MiniBike());
boss.GoToWork();
这样就可以了,这也是定义中提到的“encapsulates each one and makes them interchangeable”的意义所在。
针对接口编程而不是实现(Program to interface not implementation)。
这个就很简单了,正因为在worker类中有 protected IVehicle _vehicle,才可以实现运行时改变对象行为,对于本例来说就是可以老板愿意他可以选择骑自行车(当然他得有自行车,^_^。)
代码下载:
StrategyDemo.zip