设计模式-建造者模式

概念

将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以有不同的表示。

大概的意思是说:一套的构建过程可以有不同的产品(表示)出来。这些产品(表示)都按照这一套的构建过程被生产出来。

初探

建造者模式属于创建型模式。比如说:楼房是千差万别的,楼房的外形,层数,内部房间的数量,房间的装饰都不一样。但是对于建造者来说,抽象出来的建筑流程是确定的。因为建筑一座楼房,都可以归纳为几个步骤:1打桩、2建地基、3搭框架、4内部建设。同理,建造者设计模式也是基于这样的概念而生的,这个设计模式用来解决什么样的情况呢:即流程不变,但每个流程实现的具体细节是会变化的。这样的情况,可以考虑使用建造者。就像盖房子,4个流程都必须有,但每个流程各自的实现细节,各个房子各有不同。 建造者模式的好处就是保证了流程不会变化,即流程不会增加也不会遗漏,也不会产生流程次序的错误。而建造者模式,保证了流程的确定性,而流程内部的实现细节,是可继承扩展的。从根源上解决了流程不规范的问题。

写代码的时候,如果你遇到一个需要把控流程,但流程中的实现细节各有许多的方式,你可以采用建造者模式。用一个director类把控流程,而用许多不同的builder去建造流程中的细节并产生产品。这样,生产出来的产品基本是不会出问题的。因为流程把控好了。你可以有多个builder去负责建造生产产品,而让director去把控流程。如果有新的产品,但是流程一致,你可以再扩张出一个builder来。这样,你看,建造者模式是不是很符合OCP原则呢。

建造者模式注重于房子的零部件的组装的顺序,而工厂模式则注重于创建怎样的房子.
建造者模式要求建造的过程必须是稳定的,而装饰模式没有这个要求

模式中的角色分类

  • Builder:给出一个抽象接口,规范建造者对于生产的产品的各个组成部分的建造。这个接口只是定一个规范,不涉及具体的建造,具体的建造让继承于它的子类(ConcreteBuilder)去实现
  • ConcreteBuilder:实现builder接口,针对不同的商业逻辑,具体化各对象部分的建造,最后返回一个建造好的产品。实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品
  • Director:导演(负责人),顾名思义,负责规范流程之用。在指导中不涉及产品的创建,只负责保证复杂对象各部分被创建或按某种顺序创建。导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。
  • Product:复杂对象。

角色UML关系图如下

这里写图片描述

以创建AlertDialog为例子
目前,创建者模式,有很多变种.

标准模式

UML图如下

这里写图片描述

java代码

抽象接口

package demo10;

/**
 * 
 * @ClassName: DialogBuilder
 * @Description:抽象接口
 * @author cheng
 * @date 2017-8-15 下午02:02:06
 */
public interface DialogBuilder {
    /**
     * 
     * @Title: createBackGround
     * @Description: 创建背景
     * @param s
     * @return
     */
    DialogBuilder createBackGround(String s);

    /**
     * 
     * @Title: createShape
     * @Description: 创建形状
     * @param s
     * @return
     */
    DialogBuilder createShape(String s);

    /**
     * 
     * @Title: createTitle
     * @Description: 创建标题
     * @param s
     * @return
     */
    DialogBuilder createTitle(String s);

    /**
     * 
     * @Title: build
     * @Description: 创建对象并返回
     * @return
     */
    Object build();
}

具体实现类

package demo10;

/**
 * 
 * @ClassName: AlertDialogBuilder
 * @Description:具体构建类
 * @author cheng
 * @date 2017-8-15 下午02:13:39
 */
public class AlertDialogBuilder implements DialogBuilder {

    //持有产品的引用
    private AlertDialog alertDialog;

    public AlertDialogBuilder() {
        alertDialog = new AlertDialog();
    }

    @Override
    public DialogBuilder createBackGround(String s) {
        alertDialog.setBackGround(s);
        return this;
    }

    @Override
    public DialogBuilder createShape(String s) {
        alertDialog.setShape(s);
        return this;
    }

    @Override
    public DialogBuilder createTitle(String s) {
        alertDialog.setTitle(s);
        return this;
    }

    @Override
    public AlertDialog build() {
        return alertDialog;
    }

}

产品类

package demo10;

/**
 * 
 * @ClassName: AlertDialog
 * @Description:产品类
 * @author cheng
 * @date 2017-8-15 下午02:08:35
 */
public class AlertDialog {

    private String backGround;
    private String shape;
    private String title;

    /**
     * 复写
     */
    @Override
    public String toString() {
        return "AlertDialog[backGround=" + backGround + ",shape=" + shape
                + ",title=" + title + "]";
    }

    public AlertDialog() {
    }

    public AlertDialog(String backGround, String shape, String title) {
        super();
        this.backGround = backGround;
        this.shape = shape;
        this.title = title;
    }

    public String getBackGround() {
        return backGround;
    }

    public void setBackGround(String backGround) {
        this.backGround = backGround;
    }

    public String getShape() {
        return shape;
    }

    public void setShape(String shape) {
        this.shape = shape;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}

导演类

package demo10;

/**
 * 
 * @ClassName: DialogDirector
 * @Description:导演类
 * @author cheng
 * @date 2017-8-15 下午02:19:11
 */
public class DialogDirector {

    // 持有抽象接口的引用
    private DialogBuilder dialogBuilder;

    public DialogDirector() {
        dialogBuilder = new AlertDialogBuilder();
    }

    public AlertDialog createDialog(String background, String shape,
            String title) {
        return (AlertDialog) dialogBuilder.createBackGround(background)
                .createShape(shape).createTitle(title).build();
    }
}

测试

package demo10;

/**
 * 
 * @ClassName: ClientTest
 * @Description:测试
 * @author cheng
 * @date 2017-8-15 下午02:21:52
 */
public class ClientTest {

    public static void main(String[] args) {
        AlertDialog alertDialog1 = new DialogDirector().createDialog("黑色",
                "长方形", "是否删除");
        System.out.println(alertDialog1);
    }
}

运行结果
这里写图片描述

链式简版

只包括建造者类,产品参数内部类,产品类

UML图如下

这里写图片描述

java代码

具体建造类

package demo11;

/**
 * 
 * @ClassName: AlertDialogBuilder
 * @Description:具体构建类
 * @author cheng
 * @date 2017-8-15 下午02:13:39
 */
public class AlertDialogBuilder {

    private AlertDialogParams alertDialogParams;

    /**
     * 初始化建造者,初始化AlertDialogparams中间件
     */
    public AlertDialogBuilder() {
        alertDialogParams = new AlertDialogParams();
    }

    /**
     * 
     * @ClassName: AlertDialogparams
     * @Description:内部类来作为中间量,作为建造对象的参数传入,属性和产品类相同
     * @author cheng
     * @date 2017-8-15 下午03:58:21
     */
    class AlertDialogParams {
        String backGround;
        String shape;
        String title;
    }

    /**
     * 
     * @Title: createBackGround
     * @Description: 返回自身AlertDialogBuilder,链式调用
     * @param s
     * @return
     */
    public AlertDialogBuilder createBackGround(String s) {
        alertDialogParams.backGround = s;
        return this;
    }

    public AlertDialogBuilder createShape(String s) {
        alertDialogParams.shape = s;
        return this;
    }

    public AlertDialogBuilder createTitle(String s) {
        alertDialogParams.title = s;
        return this;
    }

    /**
     * 新建AlertDialog对象,将中间量alertDialogParams传入AlertDialog,进行构建.
     */
    public AlertDialog build() {
        AlertDialog alertDialog = new AlertDialog();
        alertDialog.init(alertDialogParams);
        return alertDialog;
    }

}

产品类

package demo11;

/**
 * 
 * @ClassName: AlertDialog
 * @Description:产品类
 * @author cheng
 * @date 2017-8-15 下午03:50:09
 */
public class AlertDialog {
    private String backGround;
    private String shape;
    private String title;

    /**
     * 
     * @Title: init
     * @Description: 初始化
     * @param params
     */
    public void init(AlertDialogBuilder.AlertDialogParams params) {
        this.backGround = params.backGround;
        this.shape = params.shape;
        this.title = params.title;
    }

    /**
     * 复写
     */
    @Override
    public String toString() {
        return "AlertDialog[backGround=" + backGround + ",shape=" + shape
                + ",title=" + title + "]";
    }

    public AlertDialog() {
    }

    public String getBackGround() {
        return backGround;
    }

    public void setBackGround(String backGround) {
        this.backGround = backGround;
    }

    public String getShape() {
        return shape;
    }

    public void setShape(String shape) {
        this.shape = shape;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}

测试

package demo11;

/**
 * 
 * @ClassName: ClientTest
 * @Description:测试
 * @author cheng
 * @date 2017-8-15 下午02:21:52
 */
public class ClientTest {

    public static void main(String[] args) {
        AlertDialog alertDialog = new AlertDialogBuilder()
                                        .createBackGround("黑色")
                                        .createShape("圆形")
                                        .createTitle("确认登录")
                                        .build();
        System.out.println(alertDialog);
    }
}

运行结果
这里写图片描述

好处

使用建造者模式可以使客户端不必知道产品内部组成的细节。
具体的建造者类之间是相互独立的,对系统的扩展非常有利。
由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

使用场合

创建一些复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,但是对象的内部组成构件面临着复杂的变化
要创建的复杂对象的算法,独立于该对象的组成部分,也独立于组成部分的装配方法时。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值