重構手法之處理概括關係【2】

来源:http://www.cnblogs.com/liuyoung/archive/2017/12/07/7965966.html
-Advertisement-
Play Games

基類中的某個函數只與部分(並非全部)子類有關。將這個函數移到相關的那些子類去。 ...


返回總目錄

本小節目錄

4Push Down Method(函數下移)

概要

基類中的某個函數只與部分(並非全部)子類有關。

將這個函數移到相關的那些子類去。

動機

Push Down Method與Pull Up Method恰恰相反。當我有必要把某些行為從基類中移至特定的子類時,就使用Push Down Method,它通常也只在這種時候有用。使用Extract Subclass之後可能會需要它。

範例

如下代碼所示,Animal類中的方法Bark()只有在其子類Dog中使用,所以最好的方案就是把這個方法移到子類Dog中。

public class Animal
{
    public void Bark()
    {
        // code to bark
    }
}

public class Dog : Animal
{
}

public class Cat : Animal
{
}

重構後的代碼如下,同時在父類Animal中如果沒有其他的欄位或者公用方法的話,可以考慮把Bark()方法做成一個介面,從而去掉Animal類。

public class Animal
{

}

public class Dog : Animal
{
    public void Bark()
    {
        // code to bark
    }
}

public class Cat : Animal
{
}

小結

面向對象三大特征(繼承、封裝、多態)很多時候可以幫助我們,但同時也可能會造成使用過度或者使用不當,所以如何把握好設計,這個就變得至關重要。在什麼時候使用繼承的方式,在什麼時候使用組合和聚合,介面和繼承類的選擇等就成了我們的重點。

5Push Down Field(欄位下移)

概要

基類中的某個欄位只被部分(並非全部)子類用到。

將這個欄位移到需要它的那些子類去。

動機

如果只有某些(而非全部)子類需要基類內的一個欄位,就可以使用本項重構。

範例

如下代碼所示,基類Task類中的_resolution欄位只會在子類BugTask中用到,所以就考慮把它放到BugTask類中。

public class Task
{
    protected string _resolution;
}

public class BugTask : Task
{
}

public class FeatureTask : Task
{
}

重構後的代碼如下所示,這樣做的好處可以簡化基類,同時讓其他沒有使用它的子類也變得更加簡單,如果這樣的欄位比較多的話,使用此重構也能節約一部分記憶體。

public class Task
{
   
}

public class BugTask : Task
{
    protected string _resolution;
}

public class FeatureTask : Task
{
}

小結

此重構也是一個非常簡單的重構,在很多時候我們都會不自覺的使用它。

6Extract Subclass(提煉子類)

概要

類中的某些特性只被某些(而非全部)實例用到。

新建一個子類,將上面所說的那一部分特性轉移到子類中。

動機

使用本項重構的主要動機是:你發現類中的某些行為只被一部分實例用到,其他實例不需要它們。

Extract Class是Extract Subclass之外的另一種選擇,兩者之間的抉擇其實就是委托和繼承之間的抉擇。Extract Subclass通常更容易進行,但它也有限制:一旦對象創建完成,你無法再改變與類型相關的行為。但如果使用Extract Class,你只需插入另一個組件就可以改變對象的行為。此外,子類只能用以表現一組變化。如果你希望一個類以幾種不同的方式變化,就必須使用委托。

範例

當你的基類中存在一些方法不是所有的子類都需要訪問,你想將它們調整到子類中時,這個重構會變得很有用了。如下代碼所示,我們需要一個 Registration類用來處理學生選課的信息。但是當Registration類開始工作後,我們意識到我們會在兩種不同的上下文中使用Registration類,NonRegistrationAction和Notes只有在我們處理未註冊情況下才用到。

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 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; }
}

小結

這個重構方法經常用來規範類的職責,和之前的一些重構方法也有些類似。

 

To Be Continued……


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.在eclipse中用maven創建項目,右鍵new>>Maven Project 2.點擊next繼續 3.點擊next繼續,選擇maven-archetype-webapp, 4.點擊next繼續,填寫Group id和Artifact id, Version預設,Package可以不填 5. ...
  • 父類和子類的轉換 向上轉型: Father f1 = new son(); 向下轉型: son f2= (son)f1; 代碼如下: 父類 子類 主程式 ...
  • 這是因為切換成了java面板的原因 因為之前有切換到過 java project 項目,所以才轉到了這個面板,之後如果不手動改即便是用javaee也會是這個面板,因而用起來不方便 解決方法: 切換到javaee面板就好了 這樣的話用起來控制台等方面就更加靈活了 ...
  • 最近在學習多線程,題目源自 MoreWindows先生的 《秒殺多線程第一篇》(http://blog.csdn.net/morewindows/article/details/7392749) 題目摘錄: 第五題(Google面試題) 有四個線程1、2、3、4。線程1的功能就是輸出1,線程2的功能 ...
  • 創建類 實例化對象 form = 類名(instance=obj,data=request.POST) instance傳的是已有的對象(在頁面中顯示預設值)data傳的是從頁面返回過來的值(用戶輸入的值 ,用來驗證) form.is_valid() #驗證 form.save #將數據保存至資料庫 ...
  • 一、ModelForm的介紹 應用場景: - ModelForm - 中小型應用程式。因為ModelForm是依賴於models的 - Form - 大型應用程式 * 註意事項: 二、表結構 三、基於Form組件的添加和編輯 添加:這隻是單表的添加 編輯:單表的編輯 具體基於Form組件實現的一對多 ...
  • Modelform組件 Modelform就是model和from兩者結合起來的。它既有驗證,又有資料庫的操作 Modelform組件: Modelform註意事項: 1、類 示列(增刪改查): url: from django.conf.urls import url from django.co ...
  • 使用synchronized雖然能夠避免不同步的現象出現,但是也會出現弊端,比如代碼執行時間過長,那麼其他線程就必須等待該線程執行完畢釋放鎖之後才能拿到鎖。 面對這種問題可以使用同步代碼塊來解決。 2.2.1synchronized方法的弊端: 任務類: 工具類: 線程代碼1: 線程代碼2: 執行代 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...