zoukankan      html  css  js  c++  java
  • Builder模式与Fluent接口

         我们首先回故下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
     
  • 相关阅读:
    [Linux] Nginx服务下统计网站的QPS
    [Go] go等待读取最后一行的数据内容
    [Go] Golang中的面向对象
    [Linux] 常见的并发模型
    [PHP] pmap可以查看进程占用内存的详细情况
    [PHP] 解决php中上传大文件的错误
    [PHP] 循环查看php-fpm的内存占用情况
    [Go] go中的goto语句跳到指定标签
    Java抽象类(Abstract Class)与接口(Interface)区别
    Java访问级别修饰符
  • 原文地址:https://www.cnblogs.com/wintersun/p/1453796.html
Copyright © 2011-2022 走看看