建造者模式
微信公众号:新时代程序猿
关注可了解更多的JAVA,PYTHON,ANDROID教程及开发技术。
问题或建议,请公众号留言;
如果你觉得文章对你有帮助,欢迎赞赏
建造者模式
前言
还是那句话,没有敲个几万行代码,谈设计模式都是瞎扯淡,咱先看看定义
在软件工程领域,设计模式是一套通用的可复用的解决方案,用来解决在软件设计过程中产生的通用问题。它不是一个可以直接转换成源代码的设计,只是一套在软件系统设计过程中程序员应该遵循的最佳实践准则。
所以说,没有工作经验或者没有项目经验,你会完全不知道设计模式在搞什么鬼~你就记住了,假如没有设计模式,软件照样开发,就是在大型软件系统开发及维护过程中就痛苦不堪,最后在不断重构后你会发现尼玛竟然用了好多设计模式。
建造者模式的定义和特点
定义虽然基本没有卵用,因为大部分人都看不懂,但是还的说出来
The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
使用场景
设计模式的核心不在于你记住某一段代码,而是在于懂得某个设计模式的思想,知道在什么情况下使用什么设计模式,这样你的代码才能易于维护,下面是建造者设计模式的使用场景:
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
解决的问题
当一个类的构造函数参数超过4个,而且这些参数有些是可选的时,我们通常有两种办法来构建它的对象。例如我们现在有如下一个类计算机类Computer,其中cpu与ram是必填参数,而其他3个是可选参数,那么我们如何构造这个类的实例呢,通常有两种常用的方式:
第一:折叠构造函数模式(telescoping constructor pattern),这个我们经常用,如下代码所示
第二种:Javabean 模式,如下所示
那么这两种方式有什么弊端呢?
第一种在穿参数的时候需要一一对应,一两个参数还好,如果是七八个参数,想想都很烦,传错了还难定位原因,熟悉代码的时候也不方便。你可以想象一下,当你要调用一个类的构造函数时,你首先要决定使用哪一个,然后里面又是一堆参数,如果这些参数的类型很多又都一样,你还要搞清楚这些参数的含义,很容易就传混了。。。那酸爽谁用谁知道。
第二种方式在构建过程中对象的状态容易发生变化,造成错误。因为那个类中的属性是分步设置的,所以就容易出错。
为了解决这两个问题,builder设计模式就出现了。
建造者模式的结构与实现
- 在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。
- 在Computer中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个public的构造函数,参数为Computer中必填的那些参数,cpu 和ram。
- 在Builder中创建设置函数,对Computer中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个build()方法,在其中构建Computer的实例并返回
如何使用
在客户端使用链式调用,一步一步的把对象构建出来。
输出:
案例
构建者模式是一个非常实用而常见的创建类型的模式(creational design pattern),例如Android开发中图片处理框架Glide,网络请求框架Retrofit等都使用了此模式。
扩展
其实上面的内容是Builder在Java中一种简化的使用方式,经典的Builder 模式与其有一定的不同,如果没有兴趣的同学就可以不用往下读了。
传统Builder 模式
构建者模式UML图如下所示
如上图所示,builder模式有4个角色。
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
我们接下来将最开始的例子使用传统方式来实现一遍。
第一步:我们的目标Computer类:
第二步:抽象构建者类
第三步:实体构建者类,我们可以根据要构建的产品种类产生多了实体构建者类,这里我们需要构建两种品牌的电脑,苹果电脑和联想电脑,所以我们生成了两个实体构建者类。
苹果电脑构建者类
戴尔电脑构建者类
第四步:指导者类(Director)
使用
- 首先生成一个director ,
- 然后生成一个目标builder,
- 接着使用director组装builder,
- 组装完毕后使用builder创建产品实例
输出结果如下:
可以看到,文章最开始的使用方式是传统builder模式的变种, 首先其省略了director 这个角色,将构建算法交给了client端,其次将builder 写到了要构建的产品类里面,最后采用了链式调用。
该模式的主要优点如下:
封装性好,构建和表示分离。
扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
其缺点如下:
产品的组成部分必须相同,这限制了其使用范围。
如果产品的内部变化复杂,或者产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
评论区