当前位置: 首页 > 科技观察

一个构造方法写了30个参数,老大看了想骂人_0

时间:2023-03-12 19:05:06 科技观察

前言一般写一两个参数还好,写七八个参数就不行了有点不舒服。如果我写十几个呢?尼玛,不舒服,我先缓一缓。于是乎,一种新的方法和策略诞生了。那就是建造者模式。当构造方法中参数过多时,创建一个类对象比较方便。所以本文的中心主题是一句话总结:当构造方法中参数过多时,建议使用构建器模式。既然推荐建造者模式,那我们就一一分析一下不使用建造者模式的弊端。一、传统方法的缺点1、可扩展的构造方法可扩展的构造方法是我们平时写的最常见的一种,请看下面的代码;publicclassStudent{privateintid;//必要的privateStringname;//必要的privateintage;//可选的privateintsclass;//可选的privateinheight;//可选的privatefloatweight;//可选的privatefloatscore;//可选的//构造函数1:默认构造函数publicStudent(){};//构造方法2:必填字段构造方法publicStudent(intid,Stringname){this.id=id;this.name=name;}//构造方法3:所有字段构造方法publicStudent(intid,Stringname,intage,intsclass,inheight,floatweight,floatscore){super();this.id=id;this.name=name;this.age=age;this.sclass=sclass;this.height=height;this.weight=weight;this.score=score;}}下面如果我们要创建一个Student类,一般都是这样创建的,看下面代码:publicclassMain{publicstaticvoidmain(String[]args){//1、可扩展构造方法Studentsstudent1=newStudent();Studentstudent2=newStudent(1,"愚公移山");Studentstudent3=newStudent(2,"愚公移山",18,1,175,120,99);}}现在我们列出了一个有七个字段的例子,这样更容易理解。下面我们来分析一下它有哪些缺点:缺点1:反转字段,编译器不会报错。比如上面的字段中有一个weight和一个score,都是float类型的。如果你在新建一个Student类的时候不小心把它写反了,编译器是不会注意到的。缺点二:这里只有七个字段,很难理解。如果有十多个,我们就需要不断的去Student类中查看前几个参数应该写什么,真的很麻烦。当用户看到这个Student(2,"愚公要移山",18,1,175,120,99)时,无法理解每个字段属性代表什么。缺点三:你不想设置参数,但你必须设置值。有时候我们的Student只想设置ID,name,age字段,其他的无关紧要,但是这种模式必须设置所有的属性值。既然有上面这些缺点,我们可能还会想到另一种方式,那就是javaBean。2.javaBean模式首先看下javaBean模式是怎么写的。publicclassStudent{privateintid;//必要的privateStringname;//必要的privateintage;//可选的privateintsclass;//可选的privateinheight;//可选的privatefloatweight;//可选的privatefloatscore;//可选的//构造函数1:默认构造方法publicStudent(){}//getter和setter方法publicintgetId(){returnid;}publicvoidsetId(intid){this.id=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicintgetSclass(){returnsclass;}publicvoidsetSclass(intsclass){this.sclass=sclass;}publicintgetHeight(){returnheight;}publicvoidsetHeight(intheight){this.height=height;}publicfloatgetWeight(){returnweight;}publicvoidsetWeight(floatweight){this.weight=weight;}publicfloatgetScore(){returnscore;}publicvoidsetScore(floatscore){this.score=score;};}这个模式,看起来更舒服,只需设置相应的getter和setter方法即可。让我们看看如何使用这个方法来创建一个新的Student类。publicclassMain{publicstaticvoidmain(String[]args){//2、javaBean模式Studentsstudent1=newStudent();student1.setId(1);student1.setName("愚公要移山");student1.setSclass(1);student1.setWeight(180);student1.setHeight(175);student1.setScore(100);student1.setAge(20);}}这看起来还可以,但这只是我一个一个打出来的。当我真正使用它时,我知道它也很恶心。下面就来总结一波它的缺点吧。缺点一:JavaBean在构建过程中可能处于不一致状态。JavaBeans模式本身有严重的缺陷。JavaBean在构造期间可能处于不一致状态,因为构造函数方法被拆分为多个调用。此类无法通过检查构造函数参数参数的有效性来强制一致性。尝试使用处于不一致状态的对象可能会导致与包含错误的代码有很大不同的错误,从而难以调试。我来说说我对它的理解。在上面的例子中,我们的student1对象已经调用了很多次set方法,但是有时候在使用这个bean的时候,剩下的setter方法还没有完成,所以再次调用,发现同一个javaBean出现了两种状态。所以处于不一致的状态。缺点2:无法保证javaBean的不变性使用第一种模式可伸缩构造方法实例化后不会改变可变性,所有数据都是确定的。它还可以保证线程安全。但是如果提供了setter方法,就没有保证了。例如:publicclassMain{publicstaticvoidmain(String[]args){//2、javaBean模式Studentsstudent1=newStudent();student1.setId(1);student1.setName("愚公要移山");student1.setSclass(1);student1.setWeight(180);student1.setHeight(175);student1.setScore(100);student1.setAge(20);System.out.println(student1.getName());student1.setName("冯冬冬");System.out.println(student1.getName());}}//输出结果:愚公要搬山冯冬冬可以看到我们可以多次设置Student对象的名字,但是状态是不一致。由于前两个存在各种问题。现在让我们看看今天的主题构建器模式。其次,建造者模式还是一样的。让我们来看看建造者模式是什么样子的。我们来分析一下它的优缺点。publicclassStudent{privateintid;//必要的privateStringname;//必要的privateintage;//可选的privateintsclass;//可选的privateinheight;//可选的privatefloatweight;//可选的privatefloatscore;//可选的publicStudent(Builderbuilder){this.id=builder.id;this.name=builder.name;this.age=builder.age;this.sclass=builder.sclass;this.height=builder.height;this.weight=builder.weight;this.score=builder.score;}publicstaticclassBuilder{privateintid;//necessaryprivateStringname;//必要的privateintage;//optionalprivateintsclass;//optionalprivateinheight;//optionalprivatefloatweight;//optionalprivatefloatscore;//optional//必需的参数构造方法publicBuilder(intid,Stringname){this.id=id;this.name=name;}publicBuildersetId(intid){this.id=id;returnthis;}publicBuildersetName(Stringname){this.name=name;returnthis;}publicBuildersetAge(intage){this.age=age;returnthis;}publicBuildersetSclass(intsclass){this.sclass=sclass;returnthis;}publicBuildersetHeight(intheight){this.height=height;returnthis;}publicBuildersetWeight(floatweight){this.重量=重量;returnthis;}publicBuildersetScore(floatscore){this.score=score;returnthis;}//publicStudentbuild(){returnnewStudent(this);}}}外部提供上面的代码内部构造了一个Builder类,接下来我们看如何使用publicclassMain{publicstaticvoidmain(String[]args){//3、Builder模式Studentstu=newStudent.Builder(1,"愚公要移山").setAge(20).setHeight(175).setSclass(1).setScore(100).setWeight(100).build();}}这本书也介绍了它的缺点。很直观的看到Student类的代码量增加了很多。但是对于Student类,我们只需要写一次就可以了,这就为我们创建对象带来了方便。优点一:没有字段的反转从上面可以看出,每次增加一个新的字段值,都是通过set方法完成的。它具有javaBean的优点。优势二:参数构造灵活我们写必要的字段,我们可以选择是否设置非必要的字段。优势三:没有不一致的状态。使用构建器模式,对象的创建必须等到构建完成。优势四:使用灵活可以重复使用单个构建器来构建多个对象。builder的参数可以在build方法的调用之间调整以改变创建的对象。构建器可以在创建对象时自动填充一些属性,例如每次创建对象时递增的序列号。缺点:为了创建一个对象,必须先创建它的建造者。虽然创建此构建器的成本在实践中不太可能被注意到,但在性能关键的情况下可能会出现问题。此外,构建器模式比伸缩构造器模式更冗长,因此只有在参数足够多(比如四个或更多)时才值得使用它。但是,如果从构造函数或者静态工厂开始,转而使用构建器,当类进化到参数个数失控的时候,过时的构造函数或者静态工厂就会面临尴尬的境地。因此,最好从一开始就创建一个构建器。综上所述,如果我们的参数比较多,builder模式是一个不错的选择。如果参数很少,由于Builder本身也是一个占用一定资源的对象,最好使用scalable或者javaBean方式。本文转载自微信公众号《愚公要移山》,作者冯冬冬。转载本文请联系愚公移山公众号。