设计模式之建造者模式

简介: 设计模式之建造者模式

建造者模式

(1)概念

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

(2)适用场景

1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。

**注意事项:**与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

(3)代码示例

我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。

我们将创建一个表示食物条目(比如汉堡和冷饮)的 Item 接口和实现 Item 接口的实体类,以及一个表示食物包装的 Packing 接口和实现 Packing 接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。

然后我们创建一个 Meal 类,带有 ItemArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilderBuilderPatternDemo,我们的演示类使用 MealBuilder 来创建一个 Meal

整体类图:

创建一个表示食物条目和食物包装的接口。

  • Item
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:45
 */
public interface Item {
    public String name();
    public Packing packing();
    public float price();
}
  • Packing
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:46
 */
public interface Packing {
    public String pack();
}

创建实现 Packing 接口的实体类。

  • Wrapper
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:46
 */
public class Wrapper implements Packing{
    @Override
    public String pack() {
        return "Wrapper";
    }
}
  • Bottle
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:47
 */
public class Bottle implements Packing {
    @Override
    public String pack() {
        return "Bottle";
    }
}

创建实现 Item 接口的抽象类,该类提供了默认的功能。

  • Burger
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:47
 */
public abstract class Burger implements Item {
    public Packing packing(){
        return new Wrapper();
    }
    public abstract float price();
}
  • ColdDrink
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:48
 */
public abstract class ColdDrink implements Item {
    @Override
    public Packing packing() {
        return new Bottle();
    }
    @Override
    public abstract float price();
}

创建扩展了 Burger 和 ColdDrink 的实体类。

  • ChickenBurger
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:52
 */
public class ChickenBurger extends Burger {
    @Override
    public String name() {
        return "ChickenBurger";
    }
    @Override
    public float price() {
        return 50.5f;
    }
}
  • VegBurger
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:51
 */
public class VegBurger extends Burger {
    @Override
    public String name() {
        return "VegBurger";
    }
    @Override
    public float price() {
        return 25.0f;
    }
}
  • Coke
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:52
 */
public class Coke extends ColdDrink {
    @Override
    public String name() {
        return "Coke";
    }
    @Override
    public float price() {
        return 30.0f;
    }
}
  • Pepsi
package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:53
 */
public class Pepsi extends ColdDrink {
    @Override
    public String name() {
        return "Pepsi";
    }
    @Override
    public float price() {
        return 35.5f;
    }
}

创建一个 Meal 类,带有上面定义的 Item 对象。

package com.alibaba.design.builderpattern;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:56
 */
public class Meal {
    private List<Item> items = new ArrayList<Item>();
    public void addItem(Item item){
        items.add(item);
    }
    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }
    public void showItems(){
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().pack());
            System.out.println(", Price : "+item.price());
        }
    }
}

创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象。

package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-10:57
 */
public class MealBuilder {
    public Meal prepareVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }
    public Meal prepareNonVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}

客户端测试类

package com.alibaba.design.builderpattern;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/31-11:00
 */
public class Test {
    public static void main(String[] args) {
        MealBuilder mealBuilder = new MealBuilder();
        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("VegMeal");
        vegMeal.showItems();
        System.out.println("Total Cost: " +vegMeal.getCost());
        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("\n\nNon-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " +nonVegMeal.getCost());
    }
}

输出结果

(4)在源码中的体现

在StringBuilder类中的源码

@Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

再看看BeanDefinitionBuilder类

来到setFactoryMethod方法,我们写的第二种与其类似,就是典型的建造者模式

MyBatis中的SqlSessionFactoryBuilder类,也是用了建造者模式,返回SqlSessionFactory对象

看其中一个build方法

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

可以看到在parseConfiguration方法的参数就是一个根节点,内部就是各个组件的装配流程

至此可以知道XMLConfigBuilder创建复杂对象的Configuration,而SqlSessionFactoryBuilder只不过是对XMLConfigBuilder做了一层简单的封装,用建造者来包装一层建造者

再来看看SqlSessionManager类,可以明显看出多个newInnetstance重载函数的就调用了SqlSessionFactoryBuilder建造者来创建复杂对象

public class SqlSessionManager implements SqlSessionFactory, SqlSession {
  private final SqlSessionFactory sqlSessionFactory;
  private final SqlSession sqlSessionProxy;
  private ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>();
  private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
    this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[]{SqlSession.class},
        new SqlSessionInterceptor());
  }
  public static SqlSessionManager newInnetstance(Reader reader) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));
  }
  public static SqlSessionManager newInstance(Reader reader, String environment) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null));
  }
  public static SqlSessionManager newInstance(Reader reader, Properties properties) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, properties));
  }
  public static SqlSessionManager newInstance(InputStream inputStream) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, null));
  }
  public static SqlSessionManager newInstance(InputStream inputStream, String environment) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, environment, null));
  }
  public static SqlSessionManager newInstance(InputStream inputStream, Properties properties) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, properties));
  }
  public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionManager(sqlSessionFactory);
  }
  ...
}

参考:

cnblogs.com/yeweiqiang/p/12940152.html

(5)建造者模式的优缺点

  • 优点:
    1、建造者独立,易扩展。
    2、便于控制细节风险。
  • 缺点:
    1、产品必须有共同点,范围有限制。
    2、如内部变化复杂,会有很多的建造类。


相关文章
|
7月前
|
设计模式 Java
【设计模式系列笔记】建造者模式
建造者模式是一种创建型设计模式,用于将复杂对象的构建与其表示分离,使构建过程可定制。关键元素包括产品类(定义要构建的对象)、建造者接口(定义构建方法)、具体建造者类(实现构建过程)和指导者类(负责构建过程)。通过建造者模式,客户端可以灵活地创建具有不同表示的复杂对象,提高代码的可读性和可维护性,尤其适用于构建过程复杂且包含多个可选部分的情况。
139 1
|
7月前
|
设计模式 安全 Java
构建未来应用:Java设计模式 - 建造者模式(Builder)在现代编程中的应用
【4月更文挑战第7天】建造者模式是提升代码质量的关键,尤其在复杂环境中。它分步骤构建对象,将构建与表示分离,适用于UI构建、数据模型组装、配置文件解析和网络请求构造等场景。最佳实践包括明确构建步骤、提供默认值、支持链式调用和确保线程安全。然而,过多步骤、不一致状态和性能问题是使用时需注意的问题。掌握建造者模式对于现代编程至关重要。
90 3
|
3月前
|
设计模式 算法
设计模式--建造者模式 builder
这篇文章通过一个电脑购买的例子,详细解释了建造者模式的四个角色(产品类、抽象构建者、实体构建类和指导者类),并提供了相应的代码实现,阐述了建造者模式在设计复杂对象时的应用和优势。
设计模式--建造者模式 builder
|
1月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
3月前
|
设计模式 算法 Java
Java设计模式-建造者模式(6)
Java设计模式-建造者模式(6)
|
4月前
|
设计模式 XML 存储
【四】设计模式~~~创建型模式~~~建造者模式(Java)
文章详细介绍了建造者模式(Builder Pattern),这是一种创建型设计模式,用于将复杂对象的构建与其表示分离,允许分步骤创建一个复杂的对象而无需指定其内部的具体构造细节。通过定义抽象建造者、具体建造者、指挥者和产品角色,建造者模式允许通过相同的构建过程创建不同的产品表示,提高了系统的灵活性和扩展性。
|
6月前
|
设计模式 算法
建造者模式-大话设计模式
建造者模式-大话设计模式
|
7月前
|
设计模式 uml
大话设计模式(3)——造物者一般的建造者模式
大话设计模式(3)——造物者一般的建造者模式
46 1
大话设计模式(3)——造物者一般的建造者模式
|
5月前
|
设计模式 JavaScript
js设计模式【详解】—— 建造者模式
js设计模式【详解】—— 建造者模式
59 0
|
6月前
|
设计模式
设计模式-05建造者模式(Builder Pattern)
设计模式-05建造者模式(Builder Pattern)