建造者模式

1 定义域特征

定义:将一个复杂的对象构建与其表示分离,使得同样的构建过程可以创建不同的表示。特征:用户只需要指定需要建造的类型即可,对于中间的细节不考虑。

2 代码实现及分析

场景:假设一个课程有许多部分组成:PPT、视频、手记、问答,需要在应用层根据不同要求创建不同的课程并设置相应的组成部分。

course类:

//课程类
public class Course {

    private String courseName;
    private String coursePPT;
    private String courseVideo;
    //笔记
    private String courseArticle;
    //question & answer
    private String courseQA;

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCoursePPT() {
        return coursePPT;
    }

    public void setCoursePPT(String coursePPT) {
        this.coursePPT = coursePPT;
    }

    public String getCourseVideo() {
        return courseVideo;
    }

    public void setCourseVideo(String courseVideo) {
        this.courseVideo = courseVideo;
    }

    public String getCourseArticle() {
        return courseArticle;
    }

    public void setCourseArticle(String courseArticle) {
        this.courseArticle = courseArticle;
    }

    public String getCourseQA() {
        return courseQA;
    }

    public void setCourseQA(String courseQA) {
        this.courseQA = courseQA;
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }
}

CourserBuilder:抽象的课程建造者

/**
 * 课程建造者
 */
public abstract class CourseBuilder {

    public abstract void buildCourseName(String courseName);
    public abstract void buildCoursePPT(String coursePPT);
    public abstract void buildCourseVideo(String courseVideo);
    public abstract void buildCourseArticle(String courseArticle);
    public abstract void buildCourseQA(String courseQA);
    //制作一个课程
    public abstract Course makeCourse();

}

CourserActualBuilder:

/**
 * 课程的真实构建类
 */
public class CourseActualBuilder extends CourseBuilder {

    private Course course = new Course();

    @Override
    public void buildCourseName(String courseName) {
        course.setCourseName(courseName);
    }

    @Override
    public void buildCoursePPT(String coursePPT) {
        course.setCoursePPT(coursePPT);
    }

    @Override
    public void buildCourseVideo(String courseVideo) {
        course.setCourseVideo(courseVideo);
    }

    @Override
    public void buildCourseArticle(String courseArticle) {
        course.setCourseArticle(courseArticle);
    }

    @Override
    public void buildCourseQA(String courseQA) {
        course.setCourseQA(courseQA);
    }

    @Override
    public Course makeCourse() {
        return course;
    }
}

Coach:辅助类

/**
 * 课程教练,通过接收到的课程信息来构建课程。
 */
public class Coach {

    private CourseBuilder courseBuilder;

    //set方式注入
    public void setCourseBuilder(CourseBuilder courseBuilder) {
        this.courseBuilder = courseBuilder;
    }

    //根据接收到的课程的信息制作课程。
    public Course makeCourse(String courseName,String coursePPT,
                             String courseVideo,String courseArticle,
                             String courseQA){
        this.courseBuilder.buildCourseName(courseName);
        this.courseBuilder.buildCoursePPT(coursePPT);
        this.courseBuilder.buildCourseVideo(courseVideo);
        this.courseBuilder.buildCourseArticle(courseArticle);
        this.courseBuilder.buildCourseQA(courseQA);
        return this.courseBuilder.makeCourse();
    }
}

Test类:应用层

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        //多态父类引用子类实现
        CourseBuilder courseBuilder = new CourseActualBuilder();
        Coach coach = new Coach();
        //在coach中注入courseBuilder
        coach.setCourseBuilder(courseBuilder);

        Course course = coach.makeCourse("Java设计模式精讲", "Java设计模式精讲PPT", "Java设计模式精讲视频",
"Java设计模式精讲手记","Java设计模式精讲问答");
System.out.println(course); } }

在应用层中通过向coach传递参数来构建一个具体的对象,coach和CourserBuilder为组合的关系,1对1。CourserActualBuilder与Course同样为组合的1对1关系,其类图关系如下图所示。

 3 优化

 对于上面的代码,coach不是必须的可以让应用层直接控制,采用静态内部类进行改善。

 Course类:

public class Course {

    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;
    //question & answer
    private String courseQA;

    //这里的CourseBuilder就是静态内部类返回的对象
    public Course(CourseBuilder courseBuilder) {
        this.courseName = courseBuilder.courseName;
        this.coursePPT = courseBuilder.coursePPT;
        this.courseVideo = courseBuilder.courseVideo;
        this.courseArticle = courseBuilder.courseArticle;
        this.courseQA = courseBuilder.courseQA;
    }

    //采用静态内部类创建Course对象
    public static class CourseBuilder{
        private String courseName;
        private String coursePPT;
        private String courseVideo;
        private String courseArticle;
        //question & answer
        private String courseQA;

        //返回对象本身可以让应用层链式调用
        public CourseBuilder buildCourseName(String courseName){
            this.courseName = courseName;
            return this;
        }


        public CourseBuilder buildCoursePPT(String coursePPT) {
            this.coursePPT = coursePPT;
            return this;
        }

        public CourseBuilder buildCourseVideo(String courseVideo) {
            this.courseVideo = courseVideo;
            return this;
        }

        public CourseBuilder buildCourseArticle(String courseArticle) {
            this.courseArticle = courseArticle;
            return this;
        }

        public CourseBuilder buildCourseQA(String courseQA) {
            this.courseQA = courseQA;
            return this;
        }

        public Course build(){
            return new Course(this);
        }
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }
}

Test类:

public class Test {
    public static void main(String[] args) {
        //链式调用
        Course course = new Course.CourseBuilder().buildCourseName("Java设计模式精讲").buildCoursePPT("Java设计模式精讲PPT").buildCourseVideo("Java设计模式精讲视频").build();
        System.out.println(course);
    }
}

这样其类比上部分要简化很多,其关系图如下:

4  源码分析

(1)JDK源码

 StringBuilder类中的append方法:

public StringBuilder append(StringBuffer sb) {
    super.append(sb);
    return this;
}

@Override
 public StringBuilder append(CharSequence s) {
     super.append(s);
     return this;
 }

可以看出与优化部分的代码类似StringBuilder在建造时没有采用过多的抽象而是采用链式方法直接进行修改。同样的还有StringBuffer,加了关键字synchronized保证了其线程安全

@Override
public synchronized StringBuffer append(Object obj) {
     toStringCache = null;
     super.append(String.valueOf(obj));
     return this;
}

@Override
public synchronized StringBuffer append(String str) {
     toStringCache = null;
     super.append(str);
     return this;
}

 (2)mybatis源码

 在SqlSessionFactoryBuilder类中的build方法:根据传入的confi构建默认的SqlSession

public SqlSessionFactory build(Configuration config) {
     return new DefaultSqlSessionFactory(config);
}

寻找Configuration具体怎么来的,首先在SqlSessionFactoryBuilder类中有如下代码:

//在XMLConfigBuilder完成复杂创建的基础上,做一层简单的封装,这里用建造者来包装一层建造者
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            //在建造者模式中使用建造者,XMLConfigBuilder负责完成复杂流程的创建
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();

            try {
                inputStream.close();
            } catch (IOException var13) {
                ;
            }

        }

        return var5;
 }

在上述代码中深入:var5 = this.build(parser.parse());深入parse()方法在XMLConfigBuilder类中有:此时得到了Configuration

public Configuration parse() {
        if (this.parsed) {
            throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        } else {
            this.parsed = true;
            //调用方法
            this.parseConfiguration(this.parser.evalNode("/configuration"));
            return this.configuration;
        }
}

继续深入:this.parseConfiguration方法便可达到复杂配置对象配置流程,至此建造者模式套用建造者模式的流程全部结束。

//XNode根节点,完成复杂流程的封装工作
    private void parseConfiguration(XNode root) {
        try {
            Properties settings = this.settingsAsPropertiess(root.evalNode("settings"));
            this.propertiesElement(root.evalNode("properties"));
            this.loadCustomVfs(settings);
            this.typeAliasesElement(root.evalNode("typeAliases"));
            this.pluginElement(root.evalNode("plugins"));
            this.objectFactoryElement(root.evalNode("objectFactory"));
            this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
            this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
            this.settingsElement(settings);
            this.environmentsElement(root.evalNode("environments"));
            this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
            this.typeHandlerElement(root.evalNode("typeHandlers"));
            this.mapperElement(root.evalNode("mappers"));
        } catch (Exception var3) {
            throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
        }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0


版权声明:本文为wuwu12dfda原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。