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.(保留原汁原味吧!木有翻译。)

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

VS自动生成的类图:




实例代码

  1using System;
  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

posted @ 2007-04-25 22:57  zhanqiangz(闲云野鹤)  阅读(2896)  评论(10编辑  收藏  举报