在第三講中我們主要關注了代碼重構的思想,從方法重構到類重構再到項目重構,這是一個過程,一種思想上的升華,今天將繼續我們“程序復用性設計”的旅程,說一下方法重載的重要性。
細心的朋友一定會非常關注net frameworks的源代碼,即使只能看到它內部方法的定義,也足夠了,在System.Web.Mvc這個命名空間下定義了很多關於MVC架構的東西,我們就以它為例來說一下方法重載吧!
重載的好處:
1 對方法調用的程序員來說,它是友好的(程序員只關心自己調用的方法簽名即可,不用管參數為NULL怎么辦這些邏輯)
2 對於代碼維護量來說,它是容易的(核心代碼只放在參數簽名最多的方法中)
3 對於代碼擴展來說,它是直接的(只要修改核心方法代碼即可,而不用一個方法一個方法的去COPY)
以下是InputExtensions類下的幾個方法:
1 public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name) 2 { 3 return htmlHelper.CheckBox(name, null); 4 } 5 6 public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, bool isChecked) 7 { 8 return htmlHelper.CheckBox(name, isChecked, null); 9 } 10 11 public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, IDictionary<string, object> htmlAttributes) 12 { 13 return CheckBoxHelper(htmlHelper, null, name, null, htmlAttributes); 14 } 15 16 public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, object htmlAttributes) 17 { 18 return htmlHelper.CheckBox(name, ((IDictionary<string, object>) HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes))); 19 } 20 21 public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, bool isChecked, IDictionary<string, object> htmlAttributes) 22 { 23 return CheckBoxHelper(htmlHelper, null, name, new bool?(isChecked), htmlAttributes); 24 } 25 26 public static MvcHtmlString CheckBox(this HtmlHelper htmlHelper, string name, bool isChecked, object htmlAttributes) 27 { 28 return htmlHelper.CheckBox(name, isChecked, ((IDictionary<string, object>) HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes))); 29 } 30
我們看到這是一個在視圖上建立復選框的方法,也是HtmlHelper類型的擴展方法,(即通過HtmlHelper的實例對象直接可以訪問到這個方法),它提供了六個方法重載,程序員在使用時根據業務需求去調用,而在參數最少的方法中,直接為參數賦一個默認值即可。
我的項目中的方法重載:
以下是一個通過狀態枚舉類型,產生一個下拉列表框的擴展方法,它有兩個重載方法,第一個是產生下拉列表 (public static MvcHtmlString StatusForSelectList(this HtmlHelper html)),第二個是在產生下拉列表時,給它設一個默認值( public static MvcHtmlString StatusForSelectList(this HtmlHelper html, int selectedValue)),這時使用方法重載就更友好,而另一種作法就是直接用一個方法代替,這對於調用方的程序員來說是不友好的。
下面是兩個方式的實現:
不友好的方式:
1 /// <summary> 2 /// 狀態字段下列列表框,要求調用方的程序員為它傳送一個默認值,如0,即使寫成int? selectValue,也會使程序員產生歧義 3 /// </summary> 4 /// <param name="html"></param> 5 /// <param name="selectedValue">選中的項</param> 6 /// <returns></returns> 7 public static MvcHtmlString StatusForSelectList(this HtmlHelper html, int selectedValue) 8 { 9 StringBuilder sb = new StringBuilder(); 10 sb.Append("<select name='Status' id='Status'>");
//selectedValue等於0 ,然后去進行一個邏輯的實現 11 foreach (Status i in Enum.GetValues(typeof(Status))) 12 if ((int)i == selectedValue) 13 sb.AppendFormat("<option value='{0}' selected='selected'>{1}</option>", (int)i, ((Status)i).GetDescription()); 14 else 15 { 16 if (i == Status.Normal) sb.AppendFormat("<option value='{0}' selected='selected'>{1}</option>", (int)i, ((Status)i).GetDescription()); 17 else 18 sb.AppendFormat("<option value='{0}'>{1}</option>", (int)i, ((Status)i).GetDescription()); 19 } 20 sb.Append("</select>"); 21 return MvcHtmlString.Create(sb.ToString()); 22 }
下面這種方式是我們提倡的,也是微軟主推的:
1 /// <summary> 2 /// 狀態字段下列列表框 3 /// </summary> 4 /// <param name="html"></param> 5 /// <param name="selectedValue">選中的項</param> 6 /// <returns></returns> 7 public static MvcHtmlString StatusForSelectList(this HtmlHelper html, int selectedValue) 8 { 9 StringBuilder sb = new StringBuilder(); 10 sb.Append("<select name='Status' id='Status'>"); 11 foreach (Status i in Enum.GetValues(typeof(Status))) 12 if ((int)i == selectedValue) 13 sb.AppendFormat("<option value='{0}' selected='selected'>{1}</option>", (int)i, ((Status)i).GetDescription()); 14 else 15 { 16 if (i == Status.Normal) sb.AppendFormat("<option value='{0}' selected='selected'>{1}</option>", (int)i, ((Status)i).GetDescription()); 17 else 18 sb.AppendFormat("<option value='{0}'>{1}</option>", (int)i, ((Status)i).GetDescription()); 19 } 20 sb.Append("</select>"); 21 return MvcHtmlString.Create(sb.ToString()); 22 } 23 24 /// <summary> 25 /// 狀態字段下列列表框 26 /// </summary> 27 /// <param name="html"></param> 28 /// <returns></returns> 29 public static MvcHtmlString StatusForSelectList(this HtmlHelper html) 30 { 31 return StatusForSelectList(html, 100); 32 }
這使得代碼很清晰,職責分明!