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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,682评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,277评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,083评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,763评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,785评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,624评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,358评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,261评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,722评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,030评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,737评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,360评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,941评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,057评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,237评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,976评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,659评论 18 139
  • 本文约定: 1. Nhibernate简写为NHB; 2. 本文例子的开发平台为win2000pro+sp4, s...
    壹米玖坤阅读 533评论 0 0
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,639评论 18 399
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,745评论 0 33
  • 2017/9/10【能量世界1103天】天津 豆丁能量公寓 意想不到,今天才揭开了自己留在天津的伏笔,原来上天悄悄...
    陈艳霞小树妈阅读 291评论 0 0