设计模式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.工厂模式
》注重于对象创建
》创建对象都一样
》只要创建出对象就行
浙公网安备 33010602011771号