定义:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
纯概念不太好理解,让我们来看一个需求:
现在需要制造一批不同种类的交通工具(包括汽车、摩托车、自行车……),假设所有的交通工具只有两个部分构成:引擎(热力和人力)和轮子(大小等),可以如下实现方法,抽象出交通工具Transport类:
1 public abstract class Transport 2 { 3 /// <summary> 4 /// 引擎 5 /// </summary> 6 /// <returns></returns> 7 public abstract string Engine(); 8 9 /// <summary> 10 /// 轮子 11 /// </summary> 12 /// <returns></returns> 13 public abstract string Wheel(); 14 }
制造汽车(假设所有的汽车都是一样的,贴上不同的标签就是不同的牌子)、摩托车、自行车类如下所示:(简化了Engine和Wheel的制造方法)
1 1 public class Car:Transport 2 2 { 3 3 /// <summary> 4 4 /// 热动力引擎 5 5 /// </summary> 6 6 /// <returns></returns> 7 7 public override string Engine() 8 8 { 9 9 return "Engine For Heat"; 10 10 } 11 11 12 12 /// <summary> 13 13 /// 特制轮子 14 14 /// </summary> 15 15 /// <returns></returns> 16 16 public override string Wheel() 17 17 { 18 18 return "Special wheel"; 19 19 } 20 20 }
1 public class Motorcycle:Transport 2 { 3 /// <summary> 4 /// 热动力引擎 5 /// </summary> 6 /// <returns></returns> 7 public override string Engine() 8 { 9 return "Engine For Heat"; 10 } 11 12 /// <summary> 13 /// 一般轮子 14 /// </summary> 15 /// <returns></returns> 16 public override string Wheel() 17 { 18 return "General wheel"; 19 } 20 }
1 public class Bicycle:Transport 2 { 3 /// <summary> 4 /// 人力引擎 5 /// </summary> 6 /// <returns></returns> 7 public override string Engine() 8 { 9 return "Engine For People"; 10 } 11 12 /// <summary> 13 /// 一般轮子 14 /// </summary> 15 /// <returns></returns> 16 public override string Wheel() 17 { 18 return "General wheel"; 19 } 20 }
摩托车(MotorCycle)介于Car和Bicycle之间,引擎和Car一样,Wheel和Bicycle一样,这样实现虽然解决了问题。但是有两个弊端:
一、出现比较多的重复代码,无法达到重用。而且随着需求变化,出现三轮车(Engine、Wheel和Bicycle一样)、卡车(Engine、Wheel和Car一样)……重复的部分会越来越多。
二、某一天,相关部门研究发现依靠热力的Engine排放了严重污染大气的尾气,需要用新研制的环保型Engine替换,就得要遍地寻找使用了原先落后技术制造的Engine,逐个更改……这无疑是个噩梦……
是时候让策略模式出场了,首先定义Wheel和Engine的抽象接口,然后将Wheel和Engine分别实现不同的制造方法,再改变下Transport抽象类:
IWheel和IEngine的定义:
1 public interface IWheel 2 { 3 string CreatWheel(); 4 } 5 6 7 public interface IEngine 8 { 9 string CreatEngine(); 10 }
Engine和Wheel分别分开实现各自的系列算法:
1 public class HeatEngine:IEngine 2 { 3 public string CreatEngine() 4 { 5 return "Engine From Heat"; 6 } 7 } 8 9 10 11 public class HuManEngine:IEngine 12 { 13 public string CreatEngine() 14 { 15 return "Engine From People"; 16 } 17 }
1 public class SpecialWheel:IWheel 2 { 3 public string CreatWheel() 4 { 5 return "Special Wheel"; 6 } 7 } 8 9 10 public class GeneralWheel:IWheel 11 { 12 public string CreatWheel() 13 { 14 return "General Wheel"; 15 } 16 }
修改下Transport抽象类:
1 public abstract class Transport 2 { 3 public IEngine _engine; 4 public IWheel _wheel; 5 6 public void SetEngine(IEngine engine) 7 { 8 this._engine = engine; 9 } 10 11 public void SetWheel(IWheel wheel) 12 { 13 this._wheel = wheel; 14 } 15 16 /// <summary> 17 /// 制造引擎 18 /// </summary> 19 /// <returns></returns> 20 public string Engine() 21 { 22 return this._engine.CreatEngine(); 23 } 24 25 /// <summary> 26 /// 制造轮子 27 /// </summary> 28 /// <returns></returns> 29 public string Wheel() 30 { 31 return this._wheel.CreatWheel(); 32 } 33 34 /// <summary> 35 /// 车外形 36 /// </summary> 37 /// <returns></returns> 38 public abstract string Display(); 39 }
Car、MotorCycle、Bicycle继承Transport:(因为都类似,只例举其一)
1 public class Bicycle : Transport 2 { 3 public override string Display() 4 { 5 return "With Blue Color"; 6 } 7 }
上述类和接口关系如下:
如图所示,可以动态扩展不同的Wheel和Engine。例如新增加了电动车,使用ElectricEngine和GeneralWheel,只需要新增一个ElectricEngine继承自IEngine如下:
1 public class ElectricEngine:IEngine 2 { 3 public string CreatEngine() 4 { 5 return "Engine From Electric"; 6 } 7 }
然后客户端引用IEngine的dll,不需要额外改动任何地方即可动态更改:
1 static void Main(string[] args) 2 { 3 Transport ts = new Car(); 4 ts.SetEngine(new HeatEngine()); 5 ts.SetWheel(new SpecialWheel()); 6 Console.WriteLine("===================================="); 7 Console.WriteLine(ts.Engine() + " " + ts.Wheel() + " " + ts.Display()); 8 Console.WriteLine("===================================="); 9 Console.WriteLine("Electric Engine :"); 10 ts.SetEngine(new ElecricEngine()); 11 ts.SetWheel(new GeneralWheel()); 12 Console.WriteLine(ts.Engine() + " " + ts.Wheel() + " " + ts.Display()); 13 14 Console.ReadKey(); 15 }
程序运行结果如下图所示:
=====================================================
欢迎大家指正~