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自动生成的类图:
实例代码:
2using System.Collections.Generic;
3using System.Text;
4using System.Diagnostics;
5
6namespace 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
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
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