JAVA设计模式之建造者模式
Posted itblock
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA设计模式之建造者模式相关的知识,希望对你有一定的参考价值。
一、定义
建造者模式(Builder) : 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式结构图,如下图1-1所示:
图 1-1
二、实例展示
Product类:产品类,由多个部件组成。
1 public class Product{
2 List<String> parts = new ArrayList<String>(); 3 public void Add(String part){ 4 parts.Add(part); 5 }
6 public void Show(){
7 System.out.println("产品创建----");
8 for(String part : parts){
9 System.out.println(part);
10 }
11 } 12}
Builder类:抽象建造者类,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult。
1 abstract class Builder{ 2 public abstract void BuildPartA();
3 public abstract void BuildPartB();
4 public abstract Product GetResult(); 5 }
ConcreteBuilder1:具体建造者类。
1 public class ConcreteBuilder1 extends Builder{
2 private Product product = new Product();
3 @override 4 public void BuildPartA(){ 5 product.Add("部件A"); 6 }
7 @Override
8 public void BuildPartB(){
9 product.Add("部件B");
10 }
11 @override
12 public void Product GetResult(){
13 result product;
14 } 15}
ConcreteBuilder2:具体建造者类。
1 public class ConcreteBuilder2 extends Builder{
2 private Product product = new Product();
3 @override 4 public void BuildPartA(){ 5 product.Add("部件X"); 6 }
7 @override
8 public void BuildPartB(){
9 product.Add("部件Y");
10 }
11 @override
12 public Product GetResult(){
13 return product;
14 } 15}
Director类:指挥者类。
1 public class Director{ 2 public void Construct(Builder builder){ 3 builder.BuildPartA();
4 builder.BuildPartB(); 5 } 6 }
客户端代码,客户不知道具体的建造过程。
1 public static void Main(String[] args) { 2 Director director = new Director();
3 Builder b1 = new ConcreteBuilder1();
4 Builder b2 = new ConcreteBuilder2();
5 director.Construct(b1);
6 Product p1 = b1.GetResult();
7 p1.Show();
8 director.Construct(b2);
9 Product p2 = b2.GetResult();
10 p2.Show();
11}
三、使用场景
1、需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
2、需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
3、对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
4、隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
四、使用总结
1、外观模式优点:
1) 外观模式对调用者(客户端或浏览器)屏蔽了子系统组件,减少了调用者所需处理的对象数目,使得子系统使用起来更加容易。通过引入外观模式,客户端代码将变得很简单,与之关联的对象也很少。
2)在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
3)每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽 象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合 "开闭原则"。
4)可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
2、外观模式缺点:
1) 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。
2)如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。
五、典型应用
1、java.lang.StringBuilder 中的建造者模式
StringBuilder
的继承实现关系如下图 5-1 所示
图 5-1
Appendable
接口如下:
1 public interface Appendable {
2 Appendable append(CharSequence csq) throws IOException;
3 Appendable append(CharSequence csq, int start, int end) throws IOException;
4 Appendable append(char c) throws IOException;
5 }
StringBuilder
中的 append
方法使用了建造者模式,不过装配方法只有一个,并不算复杂,append
方法返回的是 StringBuilder
自身
1 public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
2 @Override
3 public StringBuilder append(String str) {
4 super.append(str);
5 return this;
6 }
7 // ...省略...
8 }
StringBuilder
的父类 AbstractStringBuilder
实现了 Appendable
接口
1 abstract class AbstractStringBuilder implements Appendable, CharSequence {
2 char[] value;
3 int count;
4 public AbstractStringBuilder append(String str) {
5 if (str == null)
6 return appendNull();
7 int len = str.length();
8 ensureCapacityInternal(count + len);
9 str.getChars(0, len, value, count);
10 count += len;
11 return this;
12 }
13 private void ensureCapacityInternal(int minimumCapacity) {
14 // overflow-conscious code
15 if (minimumCapacity - value.length > 0) {
16 value = Arrays.copyOf(value,newCapacity(minimumCapacity));
17 }
18 }
19 // ...省略...
20 }
这里可以看出,Appendable
为抽象建造者,定义了建造方法,StringBuilder
既充当指挥者角色,又充当产品角色,又充当具体建造者,建造方法的实现由 AbstractStringBuilder
完成,而 StringBuilder
继承了 AbstractStringBuilder。
2、myBatis 中的建造者模式
org.apache.ibatis.session
包下的 SqlSessionFactoryBuilder
类,如下图 5-2 所示:
图 5-2
里边很多重载的 build
方法,返回值都是 SqlSessionFactory
,除了最后两个所有的 build
最后都调用下面这个 build
方法:
1 public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
2 SqlSessionFactory var5;
3 try {
4 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
5 var5 = this.build(parser.parse());
6 } catch (Exception var14) {
7 throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
8 } finally {
9 ErrorContext.instance().reset();
10 try {
11 reader.close();
12 } catch (IOException var13) {
13 ;
14 }
15 }
16 return var5;
17 }
其中最重要的是 XMLConfigBuilder
的 parse
方法,代码如下:
1 public class XMLConfigBuilder extends BaseBuilder {
2 public Configuration parse() {
3 if (this.parsed) {
4 throw new BuilderException("Each XMLConfigBuilder can only be used once.");
5 } else {
6 this.parsed = true;
7 this.parseConfiguration(this.parser.evalNode("/configuration"));
8 return this.configuration;
9 }
10 }
11 private void parseConfiguration(XNode root) {
12 try {
13 Properties settings = this.settingsAsPropertiess(root.evalNode("settings"));
14 this.propertiesElement(root.evalNode("properties"));
15 this.loadCustomVfs(settings);
16 this.typeAliasesElement(root.evalNode("typeAliases"));
17 this.pluginElement(root.evalNode("plugins"));
18 this.objectFactoryElement(root.evalNode("objectFactory"));
19 this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
20 this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
21 this.settingsElement(settings);
22 this.environmentsElement(root.evalNode("environments"));
23 this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
24 this.typeHandlerElement(root.evalNode("typeHandlers"));
25 this.mapperElement(root.evalNode("mappers"));
26 } catch (Exception var3) {
27 throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
28 }
29 }
30 // ...省略...
31 }
parse
方法最终要返回一个 Configuration
对象,构建 Configuration
对象的建造过程都在 parseConfiguration
方法中,这也就是 Mybatis
解析 XML配置文件
来构建 Configuration
对象的主要过程
参考:
1、https://mp.weixin.qq.com/s?__biz=MzI1NDU0MTE1NA==&mid=2247483712&idx=1&sn=1ffd9837eb9413dde74ff509bf69ecc5&chksm=e9c2ed4ddeb5645b8cbf64c83d103a859ae49921c60e17fe8bebe63c26b04966be101d598848&scene=0#rd
2、大话设计模式。
以上是关于JAVA设计模式之建造者模式的主要内容,如果未能解决你的问题,请参考以下文章