设计模式之建造者模式
设计模式的六大原则
设计模式对于程序员而言并不陌生,每个程序员在编程时都会或多或少地接触到设计模式。无论是在大型程序的架构中,亦或是在源码的学习中,设计模式都扮演着非常重要的角色。面向对象结合设计模式,才能真正体会到程序变得可维护、可复用、可扩展、灵活性好。
谈到设计模式就不得不说设计模式之魂:六大原则。
设计模式基于六大原则:
- 开闭原则:一个软件实体(如类、模块和函数)应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
- 单一职责原则:一个类只做一件事,一个类应该只有一个引起它修改的原因。
- 里氏替换原则:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
- 依赖倒置原则:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。关键点:1. 高层模块不应该依赖低层模块,两者都应该依赖其抽象;2. 抽象不应该依赖细节;3. 细节应该依赖抽象
- 迪米特法则:又名「最少知道原则」,一个软件实体应当尽可能少地与其他实体发生相互作用。
- 接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
所有的设计模式都是为了程序能更好的满足这六大原则。设计模式一共有 23 种,5种构建型模式:
- 工厂方法模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式
构建型模式,主要解决如何灵活创建对象或者类的问题。
7 种结构型模式:
- 适配器模式
- 桥接模式
- 组合模式
- 装饰模式
- 外观模式
- 享元模式
- 代理模式
结构型模式,主要用于将类或对象进行组合从而构建灵活而高效的结构。
11种行为型设计模式:
- 责任链模式
- 命令模式
- 解释器模式
- 迭代器模式
- 中介者模式
- 备忘录模式
- 观察者模式
- 策略模式
- 状态模式
- 模板方法模式
- 访问者模式
行为型设计模式,主要解决类或者对象直接互相通信的问题。
下面介绍工作中常常使用的建造者模式,Builder 模式。
定义
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
使用场景
如果你学了个东西,都不知道用来解决什么问题,你说有什么用?理解使用场景的的重要性要远高于你是不是会实现这个模式,因为只要你知道什么问题可以使用builder模式来解决,那你即使不会写,也可以在调查相关资料后完成。这里不讲一些大而正确的术语来把你搞蒙,我们只针对具体的问题,至于延展性的思考,随着你知识的增长,逐渐会明白的。
当一个类的构造函数参数个数超过 4 个,而且这些参数有些是可选的参数,考虑使用构造者模式。
解决的问题
当一个类的构造函数参数超过 4 个,而且这些参数有些是可选的时,我们通常有两种办法来构建它的对象。例如现在有如下一个类计算机类
Computer
,其中cpu与ram是必填参数,而其它 3 个是可选参数,那么如何构造这个类的实例呢 通常有两种常用的方式
publicclass Computer {
privateString cpu;//必须
privateString ram;//必须
private int usbCount;//可选
privateString keyboard;//可选
privateString display;//可选
}
第一:折叠构造函数模式,这个我们经常用,如下代码所示
publicclass Computer {
...
public Computer(String cpu, String ram) {
this(cpu, ram, 0);
}
public Computer(String cpu, String ram, int usbCount) {
this(cpu, ram, usbCount, "罗技键盘");
}
public Computer(String cpu, String ram, int usbCount, String keyboard) {
this(cpu, ram, usbCount, keyboard, "三星显示器");
}
public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {
this.cpu = cpu;
this.ram = ram;
this.usbCount = usbCount;
this.keyboard = keyboard;
this.display = display;
}
}
第二种:Javabean 模式,如下所示
publicclassComputer {
...
public String getCpu() {
return cpu;
}
publicvoidsetCpu(String cpu) {
this.cpu = cpu;
}
public String getRam() {
return ram;
}
publicvoidsetRam(String ram) {
this.ram = ram;
}
publicintgetUsbCount() {
return usbCount;
}
...
}
那么这两种方式有什么弊端呢?
第一种主要是使用及阅读不方便。你可以想象一下,当要调用一个类的构造函数时,你首先要决定使用哪一个,然后里面又是一堆参数,如果这些参数的类型很多又都一样,你还要搞清楚这些参数的含义,很容易就传混了。。。那酸爽谁用谁知道。
第二种方式在构建过程中对象的状态容易发生变化,造成错误。因为那个类中的属性是分步设置的,所以就容易出错。
为了解决这两个痛点,builder模式就横空出世了。
如何实现
- 在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。
- 在Computer中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个
public
的构造函数,参数为Computer中必填的那些参数,cpu 和ram。 - 在Builder中创建设置函数,对Computer中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个
build()
方法,在其中构建Computer的实例并返回
下面代码就是最终的样子
publicclassComputer{
privatefinal String cpu;//必须
privatefinal String ram;//必须
privatefinal int usbCount;//可选
privatefinal String keyboard;//可选
privatefinal String display;//可选
private Computer(Builder builder){
this.cpu=builder.cpu;
this.ram=builder.ram;
this.usbCount=builder.usbCount;
this.keyboard=builder.keyboard;
this.display=builder.display;
}
public static classBuilder{
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
public Builder(String cup,String ram){
this.cpu=cup;
this.ram=ram;
}
public Builder setUsbCount(int usbCount) {
this.usbCount = usbCount;
returnthis;
}
public Builder setKeyboard(String keyboard) {
this.keyboard = keyboard;
returnthis;
}
public Builder setDisplay(String display) {
this.display = display;
returnthis;
}
public Computer build(){
return new Computer(this);
}
}
//省略getter方法
}
如何使用
在客户端使用链式调用,一步一步的把对象构建出来。
Computer computer=new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
构建者模式是一个非常实用而常见的创建类型的模式,例如Flink、Flume 使用了此模式。
侠天,专注于大数据、机器学习和数学相关的内容,并有个人公众号:bigdata_ny分享相关技术文章。
若发现以上文章有任何不妥,请联系我。
关键词
对象
设计模式
问题
类型
参数
最新评论
推荐文章
作者最新文章
你可能感兴趣的文章
Copyright Disclaimer: The copyright of contents (including texts, images, videos and audios) posted above belong to the User who shared or the third-party website which the User shared from. If you found your copyright have been infringed, please send a DMCA takedown notice to [email protected]. For more detail of the source, please click on the button "Read Original Post" below. For other communications, please send to [email protected].
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。