Java方法參數過多

重構--Java方法參數過多

  • 示例方法
public void getNews(Context context,
                        Callback callback,
                        String uuid,
                        String uid,
                        String from,
                        String token,
                        String uid,
                        String .....){
                        //邏輯
}
  • 示例構造函數
public class Person {
    public String lastName;
    public String firstName;
    public String middleName;
    public String salutation;
    public String suffix;
    public String streetAddress;
    public String city;
    public String state;
    public boolean isFemale;
    public boolean isEmployed;
    public boolean isHomeOwner;
    public Person(String lastName, String firstName, String middleName, String salutation,
                  String suffix, String streetAddress, String city, String state,
                  boolean isFemale, boolean isEmployed, boolean isHomeOwner) {
        this.lastName = lastName;
        this.firstName = firstName;
        this.middleName = middleName;
        this.salutation = salutation;
        this.suffix = suffix;
        this.streetAddress = streetAddress;
        this.city = city;
        this.state = state;
        this.isFemale = isFemale;
        this.isEmployed = isEmployed;
        this.isHomeOwner = isHomeOwner;
    }
}
  • 問題:
    • 添加大量參數理解難度

    • 易參數位置不正確且運行正常

    • 不易維護

    • 那一個方法或者構造方法多少個參數才好了--沒有答案

      函數參數的理想個數是零,其次是一,緊隨其后的是二,應該盡可能避免三個參數的情況。參數如果多于三個則需要特殊的理由,而且無論如何都不應該再使用。
      
      • Steve McConnell在Code Complete中寫到:開發者應該限制參數在七個以內
解決方法
  • 引入參數對象
    • 參數關系緊密合并到一個對象中
      • Person.class
public class Person {
    public FullName fullName;
    public Address address;
    public boolean isFemale;
    public boolean isEmployed;
    public boolean isHomeOwner;
    public Person(FullName fullName, Address address, boolean isFemale, boolean isEmployed, boolean isHomeOwner) {
        this.fullName = fullName;
        this.address = address;
        this.isFemale = isFemale;
        this.isEmployed = isEmployed;
        this.isHomeOwner = isHomeOwner;
    }
}
  • FullName.class
public class FullName {
    public String lastName;
    public String firstName;
    public String middleName;
    public String salutation;
    public String suffix;
    public FullName(String lastName, String firstName, String middleName, String salutation, String suffix) {
        this.lastName = lastName;
        this.firstName = firstName;
        this.middleName = middleName;
        this.salutation = salutation;
        this.suffix = suffix;
    }
}
  • Address.class
 public class Address {
    public String streetAddress;
    public String city;
    public String state;
    public Address(String streetAddress, String city, 
                              String state) {
        this.streetAddress = streetAddress;
        this.city = city;
        this.state = state;
    }
}
  • 問題:參數對象可能被濫用。如果一個開發者純粹為了減少參數數量,把聯系不緊的幾個參數強捆在一個類中這肯定是行不通的,在可讀性上甚至適得其反。
  • Builder模式:
    • 需求:當一個對象需要不同的參數構造方法?不能寫5*5滿足所有的需求吧
    • 適用范圍:構建對象時,如果碰到類有很多參數——其中很多參數類型相同而且很多參數可以為空時,使用Builder模式來完成。當參數數量不多、類型不同而且都是必須出現時,通過增加代碼實現Builder往往無法體現它的優勢。在這種情況下,理想的方法是調用傳統的構造函數。再者,如果不需要保持不變,那么就使用無參構造函數調用相應的set方法吧。
    • 代碼
    • Person.class
public class Person {
    public FullName fullName;
    public Address address;
    public boolean isFemale;
    public boolean isEmployed;
    public boolean isHomeOwner;
    public Person(FullName fullName, Address address, boolean isFemale, boolean isEmployed, boolean isHomeOwner) {
        this.fullName = fullName;
        this.address = address;
        this.isFemale = isFemale;
        this.isEmployed = isEmployed;
        this.isHomeOwner = isHomeOwner;
    }
      public static class Builder {
        private FullName fullName;
        private Address address;
        private boolean isFemale;
        private boolean isEmployed;
        private boolean isHomeOwner;
        /**
         * 如果有必填參數這里可以構造必填構造方法
         */
        public Builder() {
        }
        public Builder setFullName(FullName fullName) {
            this.fullName = fullName;
            return this;
        }
        public Builder setAddress(Address address) {
            this.address = address;
            return this;
        }
        public Builder setFemale(boolean female) {
            isFemale = female;
            return this;
        }
        public Builder setEmployed(boolean employed) {
            isEmployed = employed;
            return this;
        }
        public Builder setHomeOwner(boolean homeOwner) {
            isHomeOwner = homeOwner;
            return this;
        }
        public Person create() {
            return new Person(fullName, address, isFemale, isEmployed, isHomeOwner);
        }
    }
}
  • FullName.class
public class FullName {
    public String lastName;
    public String firstName;
    public String middleName;
    public String salutation;
    public String suffix;
    public FullName(String lastName, String firstName, String middleName, String salutation, String suffix) {
        this.lastName = lastName;
        this.firstName = firstName;
        this.middleName = middleName;
        this.salutation = salutation;
        this.suffix = suffix;
    }
    public static class Builder {
        private String lastName;
        private String firstName;
        private String middleName;
        private String salutation;
        private String suffix;
        public Builder() {
        }
        public Builder setLastName(String lastName) {
            this.lastName = lastName;
            return this;
        }
        public Builder setFirstName(String firstName) {
            this.firstName = firstName;
            return this;
        }
        public Builder setMiddleName(String middleName) {
            this.middleName = middleName;
            return this;
        }
        public Builder setSalutation(String salutation) {
            this.salutation = salutation;
            return this;
        }
        public Builder setSuffix(String suffix) {
            this.suffix = suffix;
            return this;
        }
        public FullName create() {
            return new FullName(lastName, firstName, middleName, salutation, suffix);
        }
    }
}
  • Address.class
public class Address {
    public String streetAddress;
    public String city;
    public String state;
    public Address(String streetAddress, String city, String state) {
        this.streetAddress = streetAddress;
        this.city = city;
        this.state = state;
    }
    public static class Builder {
        private String streetAddress;
        private String city;
        private String state;
        public Builder() {
        }
        public Builder setStreetAddress(String streetAddress) {
            this.streetAddress = streetAddress;
            return this;
        }
        public Builder setCity(String city) {
            this.city = city;
            return this;
        }
        public Builder setState(String state) {
            this.state = state;
            return this;
        }
        public Address create() {
            return new Address(streetAddress, city, state);
        }
    }
}

調用的地方

public static void main(String[] args) {
        FullName fullName = new FullName.Builder().setFirstName("yes")
                .setLastName("no").create();
        Address address = new Address.Builder().setCity("china").setState("12")
                .create();
        Person person = new Person.Builder().setAddress(address)
                .setFullName(fullName).create();
    }
  • 優點:客戶端代碼的可用性和可讀性得到了大大提高,構造函數的參數數量明顯減少調用起來非常直觀。單個builder構建多個對象時Builder參數可在創建期間進行調整,還可以根據對象不同而進行改變,有效的避免重載構造函數。

  • 缺點:增加代碼量,代碼變得更加冗長(相比較參數數量的增加,相同類型的參數混在一起,可選參數的增加而言,改善代碼可讀性更有價值)

  • 重載

    • 適用范圍:方法中參數可選參數或者參數中指定參數相同
    • 代碼
    public String name(String name,int year) {
        return name+year;
    }
    /**
     * 重載
     * @param name
     * @return
     */
    public String name(String name) {
        return name+"null";
    }
    
    • 優點:遇到可選參數或者默認參數時,使用方法重載會十分有效。
  • 參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 本文約定: 1. Nhibernate簡寫為NHB; 2. 本文例子的開發平臺為win2000pro+sp4, s...
    壹米玖坤閱讀 541評論 0 0
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,739評論 18 399
  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經驗。 張土汪:刷leetcod...
    土汪閱讀 12,766評論 0 33
  • 2017/9/10【能量世界1103天】天津 豆丁能量公寓 意想不到,今天才揭開了自己留在天津的伏筆,原來上天悄悄...
    陳艷霞小樹媽閱讀 296評論 0 0