<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      小酌重構系列[11]——提取基類、提取子類、合并子類

      概述

      繼承是面向對象中的一個概念,在小酌重構系列[7]——使用委派代替繼承這篇文章中,我“父子關系”描述了繼承,這是一種比較片面的說法。后來我又在UML類圖的6大關系,描述了繼承是一種“is a kind of”關系,它更偏向于概念層次,這種解釋更契合繼承的本質。本篇要講的3個重構策略提取基類、提取子類、合并子類都是和繼承相關的,如果大家對繼承的理解已經足夠深刻了,這3個策略用起來應該會得心應手。

      提取基類

      定義:如果有超過一個類有相似的功能,應該提取出一個基類,并將共通的功能放在基類中。

      圖說

      初定關系

      下圖左定義了Department和Employee類,雖然這兩個類有一些共同的特質——“獲取年度成本”、“獲取名稱”。

      image

      在你第一眼看到這張圖時,會覺得Department和Employee會是什么關系?通常情況下,大家可能會覺得Department和Employee是一個聚合關系。

      image

      從這兩個類的特質分析,它們具有一些共同點——“獲取年度成本”、“獲取名稱”。
      如果希望重用這些共通點,我們該怎么做呢?當然是使用繼承啦。
      拿Employee繼承Department嗎?毛線啊,Department和Employee在語義上不存在“is a kind of”關系啊。我們總不能說“Employee is a kind of department”吧。

      Well,這條路子走不通,那我們換個概念來理解Department和Employee吧——Party。
      Party是個什么玩意兒?在概念上,Party表示一個群體,群體可以是一個部門,也可以是一個人。

      造句時刻

      前面講了,繼承關系可以用"is a kind of"來描述,現在咱們就用"is a kind of"造幾個句子試試。
      "Department is a kind of party."
      "Employee is a kind of party."
      "Party"概念這樣理解起來是否通順一些了呢?我覺得是通順的。

      如果你覺得它不通順,咱們換個姿勢再來造2個句子,用被動式造句。
      "Party can be a kind of department."
      "Party can be a kind of employee."

      "Party"是否也能作為Department和Employee的抽象概念呢?我仍然覺得是(如果您覺得還不是,我也沒轍了)。

      確定關系

      經過這么一番折騰后,我們終于得以見證以下關系的產生。
      注意,我們仍然保留了Department和Employee的聚合關系。

      image

      看了這幾幅圖,是否會引起你的思考呢?
      一些看似沒有特定關系的事物,可以通過抽象更高層次的概念,讓它們產生其它層面的一些關系。
      Department和Employee看似沒有繼承關系,然而通過抽象出"Party"這個概念,讓它Department和Employee產生了另外一層關系——同為Party的子類。

      示例

      重構前

      這段代碼定義了一個Dog類,并定義了兩個方法:EatFood()和Grrom(),分別表示“進食”和“訓練”行為。

      public class Dog
      {
          public void EatFood()
          {
              // eat some food
          }
      
      
          public void Groom()
          {
              // perform grooming
          }
      }
      

      EatFood()和Groom()是大多數動物的公有行為,當追加新的動物class時,也可能會有這兩個行為,我們應考慮將這兩個行為提取到基類。

      重構后

      public class Animal
      {
          public void EatFood()
          {
              // eat some food
          }
      
      
          public void Groom()
          {
              // perform grooming
          } 
      }
      
      public class Dog : Animal
      {
      
      }
      

      小提示:在提取基類時,如果當下只有一個類,你需要根據場景去分析“將來”可能發生的事情,這個例子較好地體現了這一點。
      Of course,你可以不必這么早地去提取基類,等到代碼出現2~3次重復以后再去提取也不遲。

      提取子類

      定義:如果基類的方法或屬性不是所有子類需要的,應將這些方法和屬性提取到子類中。

      圖說

      有人可能覺得基類中的方法或屬性越多越好,這樣子類只需要很少的代碼就能完成很多的功能。
      我們在基類中定義方法或屬性時,一定要事先確定基類的職責。

      初回

      下圖的Animal類定義了4個方法:Eat()、Run()、Fly()和Swim(),分別表示進食、奔跑、飛翔和浮游行為。

      image

      確實所有的動物都要進食,但世界上基本上不存在水陸空三棲動物,你以為這是傳說中的龍嗎?

      第2回

      現在你添加了一個類Mammal,它繼承了Animal類。

      image

      Eat()和Run()是哺乳動物的共通行為,Fly()和Swim()并不是所有哺乳動物都具備的能力。

      第3回

      再豐富一下咱們的動物世界,把鳥類和魚類也加進來( 哺乳動物終于不那么寂寞了,可以吃海鮮和燒雞了)。

      image

      咱們不搞特殊化,從一般化上去認知Mammal、Bird和Fish。
      一般來說,Mammal具備Eat()和Run()行為,Bird具備Eat()和Fly()行為,Fish具備Eat()和Swim()行為。

      這幅圖如果用代碼來展現,代碼量會非常少。
      雖然使用繼承可以減少代碼量,可以一定程度上達到代碼復用的目的,但這不意味著準確性,也不意味著較低的復雜性。

      以上內容已經說明了“不準確性”,即子類的行為不那么準確,那是基類強加給子類的。
      接著,我們來看看復雜性,上面這幅圖為例,我們從兩個角度來判斷復雜性:

      • 基類 + 子類的方法總數:一共16個方法
      • 每個子類的方法總數:每個子類都有4個方法

      第4回

      結合下面這幅圖,我們比較一下這兩種方式的復雜性:

      • 基類 + 子類的方法總數:一共7個方法
      • 每個子類的方法總數:每個子類都有2個方法

      image

      從數量上看,這兩種方式的復雜程度不言而喻。

      終回

      磨磨唧唧了這么久,用一幅圖來表示“提取子類”這個重構策略吧(綠色表示重構前,紅色表示重構后)。

      image

      示例

      重構前

      Registration類描述了學生選課的場景,學生選課有兩種情況——已注冊的課程和未注冊的課程。

      public class Registration
      {
          public NonRegistrationAction Action { get; set; }
          public decimal RegistrationTotal { get; set; }
          public string Notes { get; set; }
          public string Description { get; set; }
          public DateTime RegistrationDate { get; set; }
      }
      
      public class NonRegistrationAction
      {
          
      }
      

      Registration類的屬性NonRegistrationAction和Notes只有在未注冊的場景才會用到,所以可以考慮將這兩個屬性提取到子類。

      重構后

      重構時追加了NonRegistration類,這樣職責劃分就很清晰了:Registration類對應已注冊的選課場景,NonRegistration類對應未注冊的選課場景。

      public class Registration
      {
          public decimal RegistrationTotal { get; set; }
          public string Description { get; set; }
          public DateTime RegistrationDate { get; set; }
      }
      
      public class NonRegistration : Registration
      {
          public NonRegistrationAction Action { get; set; }
          public string Notes { get; set; }
      
      }
      
      public class NonRegistrationAction
      {
          
      }

      小提示:在基類中定義方法和屬性時,請確定它們是否具備“一般性”。

      合并子類

      定義:當子類所有的方法屬性完全適用于基類時,應該將這些方法和屬性提取到基類,并移除子類。

      這個重構策略比較簡單,咱就不上圖示了,直接用示例來向大家說明吧 ,有點困了2F7A6592

      示例

      重構前

      這段代碼定義了兩個類:Website和StudentWebsite,分別表示“網站”和“學生網站”( 難道還有“成人網站”?2F7BAF78[3]) 。StudentWebsite繼承自Website,StudentWebSite擴展了一個IsActive屬性,表示“是否激活”。

      public class Website
      {
          public string Title { get; set; }
          public string Description { get; set; }
          public IEnumerable<Webpage> Pages { get; set; } 
      }
      
      public class StudentWebsite : Website
      {
          public bool IsActive { get; set; }
      }
      
      public class Webpage
      {
          
      }
      

      重構后

      實際上IsActive屬性完全適用于所有的Website實例,所以沒有必要單獨地聲明一個StudentWebsite類,可以將IsActive屬性定義到Website類中,并移除StudentWebSite類(難道我的“成人網站”說沒有就沒有了嗎?)

      public class Website
      {
          public string Title { get; set; }
          public string Description { get; set; }
          public IEnumerable<Webpage> Pages { get; set; }
          public bool IsActive { get; set; }
      }
      
      public class Webpage
      {
      
      }
      

      小提示:不要盲目地創建子類,也不要盲目地在子類中定義方法和屬性,搞不好基類也要用呢。

      posted @ 2016-05-13 01:28  keepfool  閱讀(1915)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 99精品国产一区二区三区不卡| 日韩国产中文字幕精品| 秋霞人妻无码中文字幕| 亚洲人成电影在线天堂色| 视频一区视频二区视频三区| 人妻系列中文字幕精品| 久久精品波多野结衣| 在线观看美女网站大全免费| 亚洲欧洲精品成人久久曰| 欧美精品V欧洲精品| 日本午夜精品一区二区三区电影| 激情综合网五月婷婷| 午夜自产精品一区二区三区| 少妇高潮喷水在线观看| 精品国产成人午夜福利| 东方四虎在线观看av| 无码中文字幕av免费放| 国产亚洲欧洲av综合一区二区三区 | 中年国产丰满熟女乱子正在播放| 秋霞电影院午夜无码免费视频| 亚洲无人区一码二码三码| 精品成人免费自拍视频| 日韩一区在线中文字幕| 亚洲在战av极品无码| 国内精品国产三级国产a久久| 国产办公室秘书无码精品99| 国产亚洲无线码一区二区| gogogo在线播放中国| 永久黄网站色视频免费直播| 国产av亚洲精品ai换脸电影| 色一乱一伦一图一区二区精品 | 欧美福利电影A在线播放 | 18禁无遮挡啪啪无码网站破解版| 日本高清无卡码一区二区久久| 日本一区二区久久人妻高清| 日本高清一区免费中文视频| 男女猛烈激情xx00免费视频| 九九热在线观看视频精品| 男女激情一区二区三区| 望谟县| 99久久免费精品色老|