posts - 600,  comments - 561,  trackbacks - 20

     我们首先回故下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 override

      public 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);
      } 
 
 除了id,描述,你还可以增加更多的属生.ok,接下来我们需要定义一些接口,注意每一个接口有包含其它接口.
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
 
posted on 2009-05-10 21:48  PetterLiu  阅读(...)  评论(...编辑  收藏