架(jia)構,改善(shan)程序復用性(xing)的(de)設計~第四講(jiang) 方法(fa)的(de)重載真的(de)用不到嗎?
在第三講中我們主要關注了代碼重構的思想,從(cong)方法重構到(dao)類重構再到(dao)項目重構,這是一個過程,一種思想上的(de)(de)升華,今天將繼續我們“程序復用性設計”的(de)(de)旅程,說一下方法重載的(de)(de)重要(yao)性。
細心的(de)朋友一(yi)定(ding)會非(fei)常關注net frameworks的(de)源代碼,即使(shi)只能看到它內(nei)部方法的(de)定(ding)義,也足夠了(le),在(zai)System.Web.Mvc這個命名空間下定(ding)義了(le)很多關于MVC架構(gou)的(de)東西,我們就以它為例來(lai)說一(yi)下方法重載吧!
重載的好處:
1 對(dui)方法調用的(de)程序(xu)員來說,它是友好的(de)(程序(xu)員只關心自己(ji)調用的(de)方法簽名即可,不(bu)用管參數(shu)為(wei)NULL怎么辦這些邏輯)
2 對于代碼維護量來說,它是容易的(核(he)心代碼只放在參數(shu)簽名最多的方(fang)法中)
3 對于代碼(ma)擴(kuo)展來說,它是直接的(只要修改核(he)心方(fang)(fang)法代碼(ma)即可,而不用一(yi)(yi)個方(fang)(fang)法一(yi)(yi)個方(fang)(fang)法的去COPY)
以下是InputExtensions類下的幾(ji)個方法:
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類型的擴展方法,(即(ji)通過HtmlHelper的實例對象(xiang)直接(jie)可以(yi)訪問到這個(ge)(ge)方法),它提供了(le)六個(ge)(ge)方法重載,程序員在使用時根據業務(wu)需求去調用,而在參數最少的方法中(zhong),直接(jie)為參數賦一個(ge)(ge)默認值(zhi)即(ji)可。
我的項目中的方法重載:
以下是(shi)(shi)(shi)一(yi)(yi)個(ge)通過狀態(tai)枚舉類型(xing),產生(sheng)一(yi)(yi)個(ge)下拉(la)列(lie)表框(kuang)的擴展(zhan)方法,它(ta)有兩個(ge)重載(zai)方法,第一(yi)(yi)個(ge)是(shi)(shi)(shi)產生(sheng)下拉(la)列(lie)表 (public static MvcHtmlString StatusForSelectList(this HtmlHelper html)),第二個(ge)是(shi)(shi)(shi)在產生(sheng)下拉(la)列(lie)表時,給它(ta)設一(yi)(yi)個(ge)默認值( public static MvcHtmlString StatusForSelectList(this HtmlHelper html, int selectedValue)),這時使(shi)用方法重載(zai)就(jiu)更友(you)好,而(er)另一(yi)(yi)種作法就(jiu)是(shi)(shi)(shi)直接用一(yi)(yi)個(ge)方法代替,這對于調(diao)用方的程(cheng)序員來說是(shi)(shi)(shi)不友(you)好的。
下面是兩個(ge)方式的實現:
不友好的方式:
1 /// <summary> 2 /// 狀(zhuang)態字(zi)段下列列表框,要求調(diao)用方的程序(xu)員為它傳送一個默認值,如0,即使寫成int? selectValue,也會(hui)使程序(xu)員產生歧義(yi) 3 /// </summary> 4 /// <param name="html"></param> 5 /// <param name="selectedValue">選中的項(xiang)</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 ,然后去進行(xing)一個邏輯的實現 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 }
下面這種方(fang)式是我們提(ti)倡的,也(ye)是微軟主推的:
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 /// 狀態(tai)字段(duan)下列(lie)列(lie)表框 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 }
這使得(de)代(dai)碼很清晰,職責(ze)分(fen)明!