Head First Design patterns笔记-Strategy Patterns (从不同的人使用不同的交通工具上班看策略模式)
定义: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.(保留原汁原味吧!木有翻译。)
VS自动生成的类图:
实例代码:
using System;2
using System.Collections.Generic;3
using System.Text;4
using System.Diagnostics;5

6
namespace StrategyDemo7


{8

/**//// <summary>9
/// Base class for Boss, TeamMember and PM (let's call them workers).10
/// </summary>11
public abstract class Worker12

{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 Name19

{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 Worker46
public sealed class Boss : Worker47

{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 : Worker61

{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 : Worker70

{71
public PM()72

{73
Console.WriteLine("I am a project manager, but I have no my own car!");74
}75
}76
#endregion77

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 IVehicle84

{85
void Go();86
}87

88

Vehicles that implement IVehicle#region Vehicles that implement IVehicle89
public sealed class MiniBike : IVehicle90

{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 : IVehicle97

{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 : IVehicle105

{106
public void Go()107

{108
Console.WriteLine("I'm a millionaire, car is my daily vehicle!");109
}110
}111
#endregion112

113

114
class Program115

{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

