建立型java
建造者模式和工廠模式比較接近,其中建造者模式強調的方法的調用順序。而工廠模式強調的是建立產品。另外他們的建立粒度也不一樣。建造者模式建立出來的產品複雜的,而工廠模式建立出出來的都是一個樣。工廠模式注重的是把這個對象建立出來就能夠。建造者模式不只要建立產品還要知道這個產品的部件組成。設計模式
下面開始簡單粗暴看代碼 業務場景假設咱們如今要製做課程,這個課程須要視頻、ppt、文章的信息。同時咱們在製做課程的時候還須要一個指導老師。mybatis
首先咱們來建立一個課程類,把屬性,set get toString 方法等填充一下。app
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 + '\'' +
'}';
}
}
複製代碼
緊接着咱們建立一個抽象建造方法ide
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();
}
複製代碼
實體建造方法測試
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;
}
}
複製代碼
咱們前面說了這個課程咱們還有個指導老師,下面咱們來建立一個指導老師類。 經過這個指導老師咱們對屬性進行注入同時返回建造好了的對象。優化
public class Coach {
private CourseBuilder courseBuilder;
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();
}
}
複製代碼
最後是測試類ui
public class BuilderTest {
public static void main(String[] args) {
CourseBuilder courseBuilder = new CourseActualBuilder();
Coach coach = new Coach();
coach.setCourseBuilder(courseBuilder);
Course course = coach.makeCourse("Java設計模式精講",
"Java設計模式精講PPT",
"Java設計模式精講視頻",
"Java設計模式精講筆記",
"Java設計模式精講問答");
System.out.println(course);
}
}
複製代碼
這個上面的代碼是能夠優化的,咱們能夠將課程類和課程的類的建造者放在同一個類中,將建造寫成課程類的內部類。下面開始給出代碼。 這裏同時也使用了鏈式調用的方法。this
public class Course {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
//question & answer
private String courseQA;
public Course(CourseBuilder courseBuilder) {
this.courseName = courseBuilder.courseName;
this.coursePPT = courseBuilder.coursePPT;
this.courseVideo = courseBuilder.courseVideo;
this.courseArticle = courseBuilder.courseArticle;
this.courseQA = courseBuilder.courseQA;
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", coursePPT='" + coursePPT + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseArticle='" + courseArticle + '\'' +
", courseQA='" + courseQA + '\'' +
'}';
}
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);
}
}
}
複製代碼
此時應用的使用即爲以下spa
public class V2BuilderTest {
public static void main(String[] args) {
Course course = new Course.CourseBuilder().buildCourseName("Java設計模式精講")
.buildCoursePPT("Java設計模式精講PPT").buildCourseVideo("Java設計模式精講視頻").build();
System.out.println(course);
}
}
複製代碼
下面咱們一塊兒來看一下mybatis中對於建造者模式的應用吧,首先咱們打開SqlSessionFactoryBuilder這個類。
從圖中咱們很明顯能夠看出這些方法都是返回這個SqlSessionFactory對象 還有這個XMLConfigBuilder(reader, environment, properties)明顯就是解析mybatis xml配置的。 這裏核心就是builder方法咱們來看一下默認的builder方法。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
複製代碼
這裏將配置傳給默認的工廠進行構造。而Configuration是怎麼來的呢,咱們查看一下這個方法build(Reader reader, String environment, Properties properties)
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
複製代碼
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);這個方法是在建造這種再使用建造者。對xml文件解析,這裏調用了parse方法,咱們再查看一下這個parse方法看看。
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
複製代碼
這裏調用了parseConfiguration,咱們再進去看一下這個裏面parseConfiguration方法。
private void parseConfiguration(XNode root) {
try {
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
複製代碼
看到這裏就很是清晰了,他主要負責個個組件的構建和裝配。從上到下就是整個裝配的流程。這纔是複雜整個構建的核心,而SqlSessionFactory只是對構建進行封裝而已,因此咱們這個是建造者裏面使用建造者。