开头日常吹牛
我想大家在平时写代码的过程中肯定会去想这个类我怎么写简洁点,或者后面容易维护些.毕竟项目一大起来,代码量上去了以后,就算之前写的时候有写注释,但回过头来看总是需要再捋一遍,这就很浪费时间,毕竟大家都不想拿自己的下班时间来加班,程序员要懒一点好.这个时候设计模式的应用开始变得重要起来.在这里给大家安利一点小小的设计模式
关于设计模式,社区里已经很多人写过,也有更清楚更详细的介绍,总的来看,java有26种设计模式从类型上来说就有创建型,结构型.行为型,再细分下去就是各个具体的模式了.但是常用的就那么几个,这其中就包括单例(我觉得这个应该是很多人第一个学会的),简单工厂,建造者模式,这几个算是创建型里面比较经典的,其余还有策略模式,适配器,装饰者模式,也是比较常见的.
我觉得,这里我们可以来一波小小的介绍.那我们给个平时的开发场景出来,方便大家来点假设性行为.
开始假设性行为
假设我现在要设计一个类,但是这个类里面好几个的成员变量,我不光要创建,我还要赋值.那这个,简单啊,老夫操起键盘就是一顿啪啪啪啪啪啪啪,一分钟不到,我把所有的类跟成员写完,不光如此,我还附赠了一堆方法,包括get,set,toString,equals跟hashcode,于是我得意洋洋的说一声,搞定!
/**
* 示例类,房子
* */
public class MyHome {
private String mDoor;
private String mKitchen;
private String mToilet;
private String mBathroom;
private String mStudy;
public String getDoor() {
return mDoor;
}
public void setDoor(String mDoor) {
this.mDoor = mDoor;
}
public String getKitchen() {
return mKitchen;
}
public void setKitchen(String mKitchen) {
this.mKitchen = mKitchen;
}
public String getToilet() {
return mToilet;
}
public void setToilet(String mToilet) {
this.mToilet = mToilet;
}
public String getBathroom() {
return mBathroom;
}
public void setBathroom(String mBathroom) {
this.mBathroom = mBathroom;
}
public String getStudy() {
return mStudy;
}
public void setStudy(String mStudy) {
this.mStudy = mStudy;
}
public MyHome() {
}
public void entering() {
System.out.println("I entering in myHome");
}
}
心里头喊着舒服!这年头写代码就是那么畅快,全赖IntelliJ开发的IDE,哼哼非常好用,写完一个Alt+Insert,点点就完事了.
恩好,我得意洋洋的写完,好,我现在我要创建这个类了,于是我一个new方法,new出了对象之后,就是一次次地set赋值,给成员变量赋值需要几个就来几个set,如果我成员变量更多的话呢,不怕,出来就是下面这样
恩,我的代码很牛逼.
MyHome myHome = new MyHome();
myHome.setBackyard();
myHome.setBasement();
myHome.setBathroom();
myHome.setCourtyard();
myHome.setDoor();
myHome.setGate();
myHome.setKitchen();
myHome.setStudy();
myHome.setSwimmingPond();
myHome.setToilet();
然后,我感觉不行,要不我所有都在初始化的时候做了吧,这样会不会比较舒服?想想又觉得自己更牛掰了.
public MyHome(String mDoor, String mGate, String mCourtyard, String mBackyard, String mSwimmingPond,
String mBasement, String mKitchen, String mToilet, String mBathroom, String mStudy) {
this.mDoor = mDoor;
this.mGate = mGate;
this.mCourtyard = mCourtyard;
this.mBackyard = mBackyard;
this.mSwimmingPond = mSwimmingPond;
this.mBasement = mBasement;
this.mKitchen = mKitchen;
this.mToilet = mToilet;
this.mBathroom = mBathroom;
this.mStudy = mStudy;
}
public MyHome() {
}
那么问题来了,我现在发现我好像不需要对某个属性赋值,因为赋了也用不着,算了吧.简单,我弄多一个构造方法,不给它赋值就完事了,好,我又创建一个了一个特殊的构造方法.
public MyHome(String mCourtyard, String mBackyard, String mSwimmingPond, String mBasement, String mKitchen) {
this.mCourtyard = mCourtyard;
this.mBackyard = mBackyard;
this.mSwimmingPond = mSwimmingPond;
this.mBasement = mBasement;
this.mKitchen = mKitchen;
}
public MyHome(String mToilet, String mBathroom, String mStudy) {
this.mToilet = mToilet;
this.mBathroom = mBathroom;
this.mStudy = mStudy;
}
或者我觉得这样不行,一堆构造方法不好看,那可以啊,在有参的构造方法里随便给个数,或者赋值一个null,开心.
很好,我现在有两个呢,三个呢,继续随便给数或者null?所以我要创建一个对象我要一堆的null作为参数传进去,那个画面我真的不敢想象.像这样
public class BuilderTest {
public static void main(String[] args){
MyHome myHome = new MyHome(null, "gate", null, null, null
, null, null, null, null, null);
}
}
分析
首先,这会导致冗余的构造方法出现,如果我有10个成员变量,我就需要有无参的,还有剩下一堆随意搭配的有参构造方法.真的是随意搭配
其次,外部使用的时候就只需要这个对象,对外暴露的就只有类对象获取,不需要关注其内部创建细节.也不符合类设计的原则
而现在我们的情况就像是,我买了房子后,我要自己对房子里的一切再进行安排规划最后入住。
换个思路
那既然这样,我们干脆让售楼处了解我的需求,我说清楚,我只管买房子跟入住。从代码上讲也就是我不去主动控制这个类,我交由一个Builder类去创建,对外使用的时候我们就只需要new出一个Builder对象,然后调用其buildXXXMethod方法,最后一个build方法,创建这个目标类的对象
/**
* 建造者抽象类
*
* Created by wangshaobin on 7/30/18.
*/
abstract class AbsBuilder<T> {
/**
* 建造者建造后要返回的对象
* */
abstract T build();
/*
* 相关操作
* */
abstract T planningDoor();
abstract T planningKitchen();
abstract T planningToilet();
abstract T planningBathroom();
abstract T planningStudy();
}
/**
* 具体实现的建造者,核心类
* */
class HomeBuilder extends AbsBuilder{
private MyHome mMyHome = new MyHome();
@Override
MyHome build() {
return mMyHome;
}
@Override
HomeBuilder planningDoor(String door) {
mMyHome.setDoor(door);
return this;
}
@Override
HomeBuilder planningKitchen(String kitchen) {
mMyHome.setDoor(kitchen);
return this;
}
@Override
HomeBuilder planningToilet(String toilet) {
mMyHome.setDoor(toilet);
return this;
}
@Override
HomeBuilder planningBathroom(String bathroom) {
mMyHome.setDoor(bathroom);
return this;
}
@Override
HomeBuilder planningStudy(String study) {
mMyHome.setDoor(study);
return this;
}
}
/**
* 售楼处类
*
* Created by wangshaobin on 7/30/18.
*/
class HomeProvider {
/**
* 售楼处将用户需求交给建造者,由建造者去创建房屋对象
*
* @param level 档次
* */
static MyHome commandBuilder(String level) {
HomeBuilder homeBuilder = new HomeBuilder();
return homeBuilder
.planningBathroom(level+"浴室")
// .planningDoor(level+"门")
.planningKitchen(level+"厨房")
.planningStudy(level+"书房")
.planningToilet(level+"厕所")
.build();
}
}
上面定义了一个建造者类负责接收我的需求,这样一来我就把我的需求告诉售楼处即可,由建造者他们帮我规划好,我只需要拿到房子并使用房子即可,在代码中调用如下。
MyHome myHome = HomeProvider.commandBuilder("高级");
myHome.entering();
优缺点
先说说优点
首先是易于解耦,将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。
其次易于精确控制对象的创建,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
最后是易于拓展,增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。
缺点方面
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制;如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
应用场景
需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
以上就是我对建造者模式的介绍,有什么说得不到位的还请大家批评指正