美文网首页
Java方法参数过多

Java方法参数过多

作者: WilsonMing | 来源:发表于2016-04-15 16:08 被阅读3345次

重构--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";
    }
    
    • 优点:遇到可选参数或者默认参数时,使用方法重载会十分有效。
  • 参考资料

相关文章

网友评论

      本文标题:Java方法参数过多

      本文链接:https://www.haomeiwen.com/subject/yakmlttx.html