java 建造者模式的实际应用场景

开头日常吹牛

我想大家在平时写代码的过程中肯定会去想这个类我怎么写简洁点,或者后面容易维护些.毕竟项目一大起来,代码量上去了以后,就算之前写的时候有写注释,但回过头来看总是需要再捋一遍,这就很浪费时间,毕竟大家都不想拿自己的下班时间来加班,程序员要懒一点好.这个时候设计模式的应用开始变得重要起来.在这里给大家安利一点小小的设计模式

关于设计模式,社区里已经很多人写过,也有更清楚更详细的介绍,总的来看,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();

优缺点

先说说优点

首先是易于解耦,将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。

其次易于精确控制对象的创建,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰

最后是易于拓展,增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。

缺点方面

建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制;如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

应用场景

需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品

以上就是我对建造者模式的介绍,有什么说得不到位的还请大家批评指正

参考资料如下,如有冒犯,麻烦私信沟通:

https://blog.csdn.net/carson_ho/article/details/54910597

https://www.cnblogs.com/foryang/p/5849402.html

猜你喜欢

转载自blog.csdn.net/arthurs_l/article/details/81287128