建造者模式(Builder)

建造者模式是用来解决产品对象的创建过程是由多个零件组成的情况,这些零件与产品本身是组合关系,也就是部分与整体,这些零件的创建顺序,还有一些创建中的逻辑,都是稳定的,可以封装起来的.

例如,一个邮件对象,要成功的使用前,需要设置主题,收件人,发件人,正文,附件等零件,这些零件都与邮件对象是组合关系,如果将这些创建逻辑散落在调用处,每次使用邮件对象时都要进行繁琐的装配零件工作,而且还有可能会有一定的业务逻辑掺在这其中.

建造者模式除了将构建产品零件的算法封装起来,还可以支持消费的产品对象的动态选择,当然这也是面向对象不变的话题,封装变化点,依赖倒置.具体产品是一个对象还是一系列,这个根据实际的业务设计有所不同.

在上图中展示了一个基础的建造者模式的结构,为了尽量说明实际情况的模式环境,我们这里描绘了一个系列的产品对象.红色字体部分代表的是实现层,也就是依赖倒置原则中所讲的,不依赖实现,而依赖抽象.这里的实现层在系统中肯定是频繁变化的,而且可以随时以扩展的方式改变功能(开闭原则),而蓝色表示的是系统中的抽象层,要求是稳定的,不太能够应对频繁的功能变化.

产品对象

先从产品类来讲起,这一块通常是核心的业务骨架,对于一组产品对象,现实系统中肯定比这里的结构还要复杂,读者视自身业务情况来设计,在上图中,Product代表的是抽象产品接口,这个接口描述依赖着ProductPart,ProductPart2两个抽象的零件.这之间的关系是组合关系,换言之,就是Product的生成是需要先创建ProductPart与ProductPart2两个零件.具体的实现零件则是ConcretePart与ConcretePart2两个类来完成. ConecreteProduct是产品的具体实现类.

可以看出,红色部分的几个Conecrete开头的类,都是可以应对系统变化的,也就是我们随时可以加入ConecretePratXX 或者 ConecreteProductXXX这样的新的实现来丰富我们的系统.

封装产品的创建过程

在介绍完上边的产品结构之后,我们应该了解到Product是依赖着ProductPart与ProductPart2这两个零件的,建造者模式要封装的是这个对象的创建过程,比如:先创建Part1再创建part2,或者说part2的必须是10个以上.这就是对创建算法的封装.

Builder是抽象的建造者,其中描述buildPart()与buildPart2()两个方法分别构建不同的零件.getProduct()返回最终的产品对象Product.

ConcreteBuilder是具体的构建实现,这里与ConcretePart,ConcretePart2两个具体零件对象是关联着的,如果加入新的一套不同风格的零件,则也相应的要增加XXXConcreteBuilder,当然,如果我们很确定系统只有一种风格,那大哥不必将Builder抽象化.

Director是一个导演类,用为将具体稳定的创建算法封装在这里,比如刚才所讲的,要求创建10个Part2对象.

最后我们来看Client类,这里是指代码调用处,依赖着产品的抽象层,完全不关心具体层,在调用时只需要选择不同的ConcreteBuilder就可以完成不同风格产品的组装过程.值得说明的一点,风格是指加入不同的实现类,比如再加一套新风格,就需要加入新的派生自Product , ProductPart , ProductPart2 ,Builder的几个实现类.

具体举例说明

写到这里,也不免俗套的要举一个其实和实际开发相距甚远,还有些套路化的例子了,虽然园子里关于设计模式的文章如汗牛充栋,也有很多口号讲,不要重复搞轮子.但小弟还是认为,搞轮子和写这些文章对个人的提高是很大的,同时也能在过程中得到与别人的互动交流,设计模式本来就还有一层意思,那就是交流.我们大家都约定俗成,交流起来就更方便了不是吗,好了,各们大哥,我可以开始了吗?

假如我们有一个游戏场景,需要一个房屋,这个房屋由多面墙壁,一块地板,一块天花板组成.我们很自然的可以写出房屋,墙壁,地板,天花板对象,而且房屋与其它对象是组合关系,表现在代码中应该就是成员变量.

由于系统要求房屋有着不同的风格,比如一款普通风格,另一款精致风格.这时我们很自然的应该将房屋,地板,天花板,墙壁都抽象化.这些对象就对应前面所讲的产品结构.


package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 抽象房顶
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public abstract  class AbsRoof
{
    public abstract  String getRoofInfo() ;
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 抽象墙壁
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public abstract  class AbsWall
{
    public abstract String getWallInfo() ;
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 抽象地板
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public abstract class AbsFloor
{
    public abstract  String getFloorInfo() ;
}

package com.j2kaka.coolka.examples.pattern.builder;

import java.util.ArrayList;
import java.util.List;

/**
 * 抽象的房子类
 * @author aladdinty
 * @create 2018-01-10
 **/
public abstract  class AbsHouse
{
    private List<AbsWall> wallList ;
    private AbsFloor floor ;
    private AbsRoof roof ;

    /**添加墙壁*/
    public void addWall (AbsWall wall)
    {
        if( this.wallList == null )
        {
            this.wallList = new ArrayList<AbsWall> () ;
        }

        this.wallList.add ( wall ) ;
    }

    /**设置地板*/
    public void setFloor( AbsFloor floor )
    {
        this.floor = floor ;
    }

    /**设置天花板*/
    public  void setRoof( AbsRoof roof )
    {
        this.roof = roof ;
    }

    /**获取天花板*/
    public AbsRoof getRoof ()
    {
        return roof;
    }

    /**获取地板*/
    public AbsFloor getFloor ()
    {
        return floor;
    }

    /**获取所有墙壁*/
    public List<AbsWall> getAllWall ()
    {
        return wallList;
    }

    public String getInfo()
    {
        StringBuffer sb = new StringBuffer () ;

        for( AbsWall wall : this.wallList )
        {
            sb.append ( wall.getWallInfo () + "|") ;
        }

        return "房子的配置是这样的:" + "有几面墙:" + wallList.size () + "->" + sb.toString () + "->"+this.roof.getRoofInfo () +"->" + this.floor.getFloorInfo () ;
    }
}

好抽象层的产品描述完成了,具体产品要有对应的实现了,这里分别提供普通款与精致款风格的不同实现.

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 普通地板
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class CommonFloor extends AbsFloor
{
    @Override
    public String getFloorInfo ()
    {
        return "普通地板";
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 普通天花板
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class CommonRoof extends AbsRoof
{
    @Override
    public String getRoofInfo ()
    {
        return "普通天花板";
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 普通风格的墙面
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class CommonWall extends AbsWall
{
    @Override
    public String getWallInfo ()
    {
        return "普通墙面";
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

import java.util.ArrayList;
import java.util.List;

/**
 * 普通房子风格实现
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class CommonHouseImpl extends  AbsHouse
{
}

再来一款精致款式实现

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 精致地板
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class FinesseFloor extends AbsFloor
{
    @Override
    public String getFloorInfo ()
    {
        return "精致地板";
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 精致天花板
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class FinesseRoof extends AbsRoof
{
    @Override
    public String getRoofInfo ()
    {
        return "精致天花板";
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 精致的的墙面
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class FinesseWall extends AbsWall
{
    @Override
    public String getWallInfo ()
    {
        return "精致墙面";
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 精致风格实现
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class FinesseHouseImpl extends  AbsHouse
{
}

现目前为止,我们实现了产品的抽象化,不过还没体现出建造者模式的核心,我们开头就说过,要封装的是建造过程,同时可以动态选择产品的不同实现.让客户端毫不知情,下面代码中抽象的构建器描述我们的产品创建过程中用到的动作.最后要求返回房屋对象.

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 抽象建造者
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public abstract  class AbsBuilder
{
    public abstract void buildFloor() ;
    public abstract void buildRoof() ;
    public abstract void buildWall() ;
    public abstract AbsHouse getHouse() ;
}

具体实现不同的构建器,因为我们这个举例中有2套风格,分别是普通与精致风格,产品结构也有了相应的抽象体现,所以Builder的实现也是一一对应的.在这两个具体实现类里边,都是直接关联了具体的对象产品.

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 普通风格的构建器实现
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class CommonBuilderImpl extends AbsBuilder
{
    private AbsHouse house = new CommonHouseImpl () ;

    @Override
    public void buildFloor ()
    {
        house.setFloor ( new CommonFloor ());
    }

    @Override
    public void buildRoof ()
    {
        house.setRoof ( new CommonRoof ());
    }

    @Override
    public void buildWall ()
    {
        house.addWall ( new CommonWall () );
    }

    @Override
    public AbsHouse getHouse ()
    {
        return this.house;
    }
}

package com.j2kaka.coolka.examples.pattern.builder;

/**
 * 精致风格房屋构建器实现
 *
 * @author aladdinty
 * @create 2018-01-10
 **/
public class FinesseBuilderImpl extends AbsBuilder
{
    private AbsHouse house = new FinesseHouseImpl () ;

    @Override
    public void buildFloor ()
    {
        house.setFloor ( new FinesseFloor ());
    }

    @Override
    public void buildRoof ()
    {
        house.setRoof ( new FinesseRoof ());
    }

    @Override
    public void buildWall ()
    {
        house.addWall ( new FinesseWall () );
    }

    @Override
    public AbsHouse getHouse ()
    {
        return this.house;
    }
}

好了,构建器完成了,产品对象也完成了,现在到我们的工头出场了,他一声令下,给我盖..这里的工具其实是对应之前结构中的Director类,将稳定的对象结构创建步骤和算法封装起来,我们这里简单要求,要有4面墙壁,还有一个地板和一个天花板.

```package com.j2kaka.coolka.examples.pattern.builder;

/**

  • 工队领头人
  • 这个类中代表的是稳定的构建算法,是不能适应频繁变化的.
  • @author aladdinty
  • @create 2018-01-10

    **/

    public class Foreman

    {

    public static AbsHouse createMyHouse( AbsBuilder builder )

    {

    //先盖地板
    builder.buildFloor ();
    
    //接着修建四面墙壁
    for (int i = 0; i < 4; i++)
    {
        builder.buildWall ();
    }
    
    //把房顶盖上..
    builder.buildRoof ();
    
    return builder.getHouse () ;

    }

    }


最后我们看看调用处

package com.j2kaka.coolka.examples.pattern.builder;

/**

  • 调用处代码
  • @author aladdinty
  • @create 2018-01-10

    **/

    public class Client

    {

    public static void main(String[] args )

    {

    AbsHouse house = Foreman.createMyHouse ( new FinesseBuilderImpl () ) ;

    System.out.println ( house.getInfo ());

    AbsHouse house2 = Foreman.createMyHouse ( new CommonBuilderImpl () ) ;
    System.out.println ( house2.getInfo ());

    }

    }

```

其实忙活了半天,只是为调用处以后可以应对变化时不做调整,变化全部封在了后面的结构中.在这里只需要知道产品的抽象接口,调用工头类,决定使用哪种风格的构建器就可以了.

好了,欢乐时光总是过的特别快,感谢您能看到这里,希望我的付出可以给您带来一点点的帮助,如果不爽请轻虐,如果疑问欢迎留言交流

建造者模式(Builder)-宏观的使用角度的更多相关文章

  1. 【原】iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解释建造者模式的概念,那些东西太虚了.设计模式这种东西是为了解决实际问题的,不能为了设计模式而设计模式, ...

  2. iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    转自:http://www.cnblogs.com/wengzilin/p/4365855.html 本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解 ...

  3. 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)

    原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...

  4. 【设计模式】建造者模式 Builder Pattern

    前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...

  5. 建造者模式(Builder Pattern)

    建造者模式(Builder Pattern) 它可以将多个简单的对象一步一步构建成一个复杂的对象. 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 主要解决:主要解决在软 ...

  6. 二十四种设计模式:建造者模式(Builder Pattern)

    建造者模式(Builder Pattern) 介绍将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 示例用同样的构建过程创建Sql和Xml的Insert()方法和Get()方 ...

  7. 建造者模式(Builder)——从组装电脑开始

    建造者模式(Builder)--从组装电脑开始 建造者模式概括起来就是将不同独立的组件按照一定的条件组合起来构成一个相对业务完整的对象.调用者无需知道构造的过程. 我们从组装电脑开始 让我们从买组装电 ...

  8. 设计模式—建造者模式(Builder)

    title: 设计模式-建造者模式 建造者模式(Builder)是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节.建造者模式属于对 ...

  9. 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

随机推荐

  1. 基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多

    通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无 ...

  2. HDU 2298 Toxophily(公式/三分+二分)

    Toxophily Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. Ant 给project打包

    写了一段主要的war打包.编译文件复制的 ant 配置文件 xml <?xml version="1.0" encoding="utf-8"? > ...

  4. Parcel.js + Vue 2.x 极速零配置打包体验

    继 Browserify.Webpack 之后,又一款打包工具 Parcel 横空出世 Parcel.js 的官网有这样的自我介绍 “极速零配置Web应用打包工具” 简单接触了一下,单从效率上来说,确 ...

  5. Array的基本操作

    准备饿补基础技术,先来个数组的总结. 1 .合并操作    concat :   var C = A.concat(B);    用A数组合并B数组,生成新的C数组.      循环插入        ...

  6. 项目实战12.1—企业级监控工具应用实战-zabbix安装与基础操作

    无监控,不运维.好了,废话不多说,下面都是干货. 警告:流量党勿入,图片太多!!! 项目实战系列,总架构图 http://www.cnblogs.com/along21/p/8000812.html ...

  7. Zabbix安装之路

    这次的教程多半是搬运过来的,但都经过小轩亲自测试与修改了.文章最后将公布原资源地址.此篇算是整合,但又不全是整合. 依旧需求开篇:上头让小轩监控一下服务器的情况,在前几篇也有所提到.于是小轩就到处去找 ...

  8. DataBase MongoDB高级知识-易扩展

    MongoDB高级知识-易扩展 应用程序数据集的大小正在以不可思议的速度增长.随着可用宽带的增长和存储器价格的下跌,即使是一个小规模的应用程序,需要存储的数据也可能大的惊人,甚至超出了很多数据库的处理 ...

  9. vue vuex vue-rouert后台项目——权限路由(超详细简单版)

    项目地址:vue-simple-template共三个角色:adan barbara carrie 密码全是:123456 adan 拥有 最高权限A 他可以看到 red , yellow 和 blu ...

  10. Swift3.0 创建工程常用的类、三方、以及扩展 1.5

    搭建项目常用的方法属性,欢迎追加 三方: source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_framew ...