我们首先回故下Builder模式的意图: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。[DP]
那我们C#中switch语句块,从一个层面上来看,就是由几部分组成的,我们来实现一个SwitchBuilder类具有这种功能.那什么
是Fluent接口,可以先看这儿wiki.
有的时候我们需要Enum类型处理复杂的类型,有一个描述字段,或还有更多其它的字段信息.我们创建一个使用static readonly
字段的类,看下面这是一个典型的实现:
/// <summary>/// EnumType/// </summary>/// <remarks>http://wintersun.cnblogs.com</remarks>public class EnumType{public static readonly EnumType ONE = new EnumType(1, "Descr1");public static readonly EnumType TWO = new EnumType(2, "Descr2");public static readonly EnumType THREE = new EnumType(3, "Descr3");private readonly int id;private readonly string description;private EnumType(int id, string description){this.description = description;this.id = id;}public int Id{get { return id; }}public string Description{get { return description; }}#region Object's overridepublic override bool Equals(object obj){if (ReferenceEquals(null, obj)){return false;}if (ReferenceEquals(this, obj)){return true;}return obj.GetType() != typeof (EnumType) && ((EnumType) obj).Id == Id;}public override int GetHashCode(){return id.GetHashCode();}public override string ToString(){return string.Format("id:<{0}> and Descr:<{1}>", Id, Description);}
public interface IDo {void Do(); }public interface IBody : IDo {ICase Case(object obj);IDefault Default { get; } }public interface ICase {ICase Case(object obj);IBody Body(Action action); }public interface IDefault {IDo Body(Action action); }public interface ISwitch {ICase Switch(object obj); }
再我们的具体类:
public class SwitchBuilder : ISwitch, IDefault, ICase, IBody {private Action defaultAction;private object testObject;private IList<object> caseList;private readonly IDictionary<object, Action> caseActions = new Dictionary<object, Action>();private SwitchBuilder() {}public static ISwitch Create(){return new SwitchBuilder();}public ICase Switch(object obj){caseList = new List<object>();testObject = obj;return this;}public ICase Case(object obj){caseList.Add(obj);return this;}public IBody Body(Action action){foreach (var switchCase in caseList){caseActions.Add(switchCase, action);}caseList = new List<object>();return this;}public IDefault Default{get { return this; }}IDo IDefault.Body(Action action){defaultAction = action;return this;}public void Do(){foreach (KeyValuePair<object, Action> caseAction in caseActions){if (ReferenceEquals(caseAction.Key, testObject) || Equals(caseAction.Key, testObject)){caseAction.Value();return;}}if (defaultAction != null){defaultAction();}} }
如何使用呢?看这个UnitTest
[Test] public void CanCreateFluentSwitchBuilder() {EnumType state = null;EnumType enumType = EnumType.THREE;SwitchBuilder.Create().Switch(enumType).Case(EnumType.ONE).Body(() =>{Console.WriteLine(EnumType.ONE);state = EnumType.ONE;}).Case(EnumType.TWO).Case(EnumType.THREE).Body(() =>{Console.WriteLine("->" + EnumType.TWO + EnumType.THREE);state = EnumType.TWO;}).Default.Body(() => Console.WriteLine("Def")).Do();Assert.AreEqual(state, EnumType.TWO); }
那些接口的一个作用在于,保证我们的SwitchBuilder使用时,要先Create然后Switch…最后do.
结论
Builder模式与Fluent接口在很多种场景下并不是那么简单的API,有时还需要简单的验证.还有其它方式实现
Fluent接口模式,例如使用嵌套类.
Author: Petter Liu http://wintersun.cnblogs.com
Reference: source