设计模式05-建造者模式

时长:47min

1.4.2.设计模式05-建造者模式

1.1.建造者模式定义

  builder Pattern.

定义:  

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

属性创建型模式。

特征:

  用户只需要指定需要建造的类型就可以获得对象,建造过程及细节不需要了解。

 1.1.1.适用场景

  》创建对象需要进行很多步设置,但每一步之间顺序不固定【与顺序无关】

  》如果一个对象有非常复杂的内部结构【很多属性】

  》把复杂对象的创建和使用分离。

 

1.1.2.建造者模式与原型模式的区分

  原型模式:创建克隆对象------不通过构造器,进行创建。创建过程不能定制。

  建造者模式:对象构建,步骤可定制。

1.2.建造者模式标准实现示例

1.2.1.创建业务类

package com.wf.builder.general;

import lombok.Data;

/**
 * @ClassName Product
 * @Description 产品类
 * @Author wf
 * @Date 2020/5/14 9:37
 * @Version 1.0
 */
@Data
public class Product {
    private String name;

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                '}';
    }
}

1.2.2.构建体系结构代码

1.2.2.1.顶层接口
package com.wf.builder.general;

/**
 * @ClassName IBuilder
 * @Description Product实例构建接口
 * @Author wf
 * @Date 2020/5/14 9:42
 * @Version 1.0
 */
public interface IBuilder {
    Product build();
}
1.2.2.2.构建器实现
package com.wf.builder.general;

/**
 * @ClassName ConcreteBuilder
 * @Description TODO
 * @Author wf
 * @Date 2020/5/14 9:43
 * @Version 1.0
 */
public class ConcreteBuilder implements IBuilder {
    private Product product = new Product();
    @Override
    public Product build() {
        return product;
    }
}

1.2.3.客户端调用者

package com.wf.builder.general;

/**
 * @ClassName Director
 * @Description 客户端调用者
 * @Author wf
 * @Date 2020/5/14 9:45
 * @Version 1.0
 */
public class Director {
    public static void main(String[] args) {
        IBuilder builder = new ConcreteBuilder();
        System.out.println(builder.build());
    }
}

运行结果如下:

 

 

 1.2.4.系统类图

 

1.3.建造者模式的简单实现示例

  这里以,课程教学为背景,进行编码。

  课程的组成:

    预习资料【提前发出】----演讲ppt【教学资料】----》视频资料【视频提前录制好】---》课后,总结出课堂笔记

---》课后作业。

 

  注意:这些过程,之间是没有先后关系的,顺序是可以自由调整的。

  使用建造者模式,来实现这样一个场景需求:

1.3.1.业务类

package com.wf.builder.simple;

import lombok.Data;

/**
 * @ClassName Course
 * @Description 业务类:课程类
 * @Author wf
 * @Date 2020/5/14 9:51
 * @Version 1.0
 */
@Data
public class Course {
    private String name;
    private String ppt;
    private String video;
    private String note;
    private String homework;

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", ppt='" + ppt + '\'' +
                ", video='" + video + '\'' +
                ", note='" + note + '\'' +
                ", homework='" + homework + '\'' +
                '}';
    }
}

1.3.2.构建体系代码

这里直接写构建器实现,不再面向接口编程【为了简单起见】

package com.wf.builder.simple;

/**
 * @ClassName CourseBuilder
 * @Description 课程类,实例构建器
 * @Author wf
 * @Date 2020/5/14 10:02
 * @Version 1.0
 */
public class CourseBuilder {
    private Course course = new Course();
    public Course build(){
        return course;
    }

    public void addName(String name){
        course.setName(name);
    }
    public void addPpt(String ppt){
        course.setPpt(ppt);
    }
    public void addVideo(String video){
        course.setVideo(video);
    }
    public void addNote(String note){
        course.setNote(note);
    }
    public void addHomework(String homework){
        course.setHomework(homework);
    }
}

1.3.3.客户端测试代码

package com.wf.builder.simple;

/**
 * @ClassName CourseTest
 * @Description 测试类
 * @Author wf
 * @Date 2020/5/14 10:07
 * @Version 1.0
 */
public class CourseTest {
    public static void main(String[] args) {
        CourseBuilder builder = new CourseBuilder();

        //设置很多步骤
        builder.addName("设计模式");
        builder.addHomework("作业");
        builder.addPpt("ppt课件");

        System.out.println(builder.build());

    }
}

说明:

  这里是直接使用Builder来设置业务bean的属性,而不用原生bean设置属性。

  但是,这个Builder实现又把业务bean的set方法,实现了一个遍,显然。代码不优雅。

  所以,这种使用方式,基本不会出现在生产code中。

 

  所以,提出优化方案:测试类中使用buidler.xxx进行设值,builder多次出现,且意义不大。为了避免重复,

  能不能只让它出现一次,从而使用链式编程。就像StringBuilder一样。

  xxx.append().append()....

 

1.4.构建者模式之链式编程

1.4.1.业务bean定义

package com.wf.builder.chain;

import lombok.Data;

/**
 * @ClassName Course
 * @Description 业务类:课程类
 * @Author wf
 * @Date 2020/5/14 9:51
 * @Version 1.0
 */
@Data
public class Course {
    private String name;
    private String ppt;
    private String video;
    private String note;
    private String homework;

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", ppt='" + ppt + '\'' +
                ", video='" + video + '\'' +
                ", note='" + note + '\'' +
                ", homework='" + homework + '\'' +
                '}';
    }
}

1.4.2.Builder构建器修改

package com.wf.builder.chain;

/**
 * @ClassName CourseBuilder
 * @Description 课程类的构建器,通过每个方法设值后,返回this,实现链式编程
 * @Author wf
 * @Date 2020/5/14 10:02
 * @Version 1.0
 */
public class CourseBuilder {
    private Course course = new Course();
    public Course build(){
        return course;
    }

    public CourseBuilder addName(String name){
        course.setName(name);
        return this;
    }
    public CourseBuilder addPpt(String ppt){
        course.setPpt(ppt);
        return this;
    }
    public CourseBuilder addVideo(String video){
        course.setVideo(video);
        return this;
    }
    public CourseBuilder addNote(String note){
        course.setNote(note);
        return this;
    }
    public CourseBuilder addHomework(String homework){
        course.setHomework(homework);
        return this;
    }
}

1.4.3.测试类

package com.wf.builder.chain;

/**
 * @ClassName CourseTest
 * @Description 测试类
 * @Author wf
 * @Date 2020/5/14 10:07
 * @Version 1.0
 */
public class CourseTest {
    public static void main(String[] args) {
        //使用链式编程
        CourseBuilder builder = new CourseBuilder()
                .addName("设计模式")
                .addHomework("作业")
                .addPpt("ppt课件");

        System.out.println(builder.build());

    }
}

说明:

  客户端代码使用起来,很精简。

1.5.建造者模式的总结

1.5.1.建造者模式在源码中应用

1.5.1.1.jdk源码中StringBuilder
public StringBuilder append(StringBuffer sb) {
        super.append(sb);
        return this;  //返回this,实现链式编程
    }
1.5.1.2.Mybatis中CacheBuilder实现
public CacheBuilder implementation(Class<? extends Cache> implementation) {
        this.implementation = implementation;
        return this;
    }

    public CacheBuilder addDecorator(Class<? extends Cache> decorator) {
        if (decorator != null) {
            this.decorators.add(decorator);
        }

        return this;
    }

    public CacheBuilder size(Integer size) {
        this.size = size;
        return this;
    }
1.5.1.3.Mybatis中SqlSessionFactoryBuilder
public class SqlSessionFactoryBuilder {
    public SqlSessionFactoryBuilder() {
    }

    public SqlSessionFactory build(Reader reader) {
        return this.build((Reader)reader, (String)null, (Properties)null);
    }

    public SqlSessionFactory build(Reader reader, String environment) {
        return this.build((Reader)reader, environment, (Properties)null);
    }

    public SqlSessionFactory build(Reader reader, Properties properties) {
        return this.build((Reader)reader, (String)null, properties);
    }
//...
1.5.1.4.Spring中BeanDefinitionBuilder

1.5.2.好处

  》封装性好,创建过程与使用结果分离。

  》扩展性好,建造类之间独立,一定程度上解耦。

  

  客户端可以使用链式编程

  Builder内部也可以定制属性设置的顺序,让客户端不用关心设值顺序问题。典型的sql拼接,sql有其自身的语法规则,

  如果客户端调用者不知道相关规则,随意设值,导致违反sql语法,就会报错。

 

1.5.3.缺点

  》产生多余的Builder对象

  》产品内部发生变化,建造者都要修改

 

1.5.4.建造者模式与工厂模式的对比

1.建造者模式

  》更注重方法的调用顺序

  》创建对象力度上,创建复杂的对象,对多个属性进行设置

  》关注点上,建造者不仅要创建出对象,还要知道对象的组成属性,是否需要设值

  》创建对象可以定制属性设置顺序,最终得到对象的属性也不一样

2.工厂模式

  》注重于对象创建

  》创建对象都一样

  》只要创建出对象就行

posted @ 2020-05-13 19:54  我爱钻研  阅读(238)  评论(0)    收藏  举报