设计模式之建造者模式

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

一、介绍

建造者模式(Builder Pattern)属于创建型设计模式,很多博客文章的对它的作用解释为用于将复杂对象的创建过程与其细节表示分离。但对于初学者来说,这句话难免有点晦涩难懂,何为复杂对象?何为创建过程,何为细节表示?

复杂对象:一个对象中的成员属性出了基本数据类型及其对应的封装类型,还包含有其他类型对象。例如:在对象A中包含对象B的引用,对象B中又包含对象C的引用。

创建过程:一个对象的实例化和初始化过程。如new一个对象后再调用其set方法为其初始化。

细节表示:在对一个对象初始化时,通过set方法表示其创建的细节。说白了,细节表示就是该对象的成员变量。

在一般情况下,我们要创建一个完整的对象时,往往是通过两个步骤完成:①实例化(即new一个对象);②初始化(即调用set方法对其属性赋值)。这是一种创建过程与细节表示耦合的情况。即:一个对象的实例化和初始化过程就表示为其创建过程;而在初始化过程中通过set方法我们又了解到了其内部属性(即细节表示)

而在建造者模式中,我们只需要通过一个对象的建造者(Builder)所提供的方法向其描述对象的细节,该然后该建造者通过其核心方法build()将对象实例化并补充其细节。这就是建造者的核心思想。

二、应用

  • java中的StringBuilder类。我们通过其提供的各种重载的append()方法,描述一个字符串的细节,最后通过toString()方法获得String实例。
  • OkHttp中应用了大量的建造者模式。如创建请求客户端时,使用OkHttpClient的内部类Builder来描述请求的细节,然后通过build()方法获得一个OkHttpClient实例。

三、案例

1. 麦当劳1+1随心配

我们以麦当劳随心配1+1套餐为例,当用户选择该套餐时,该套餐规定选择一个任意主食 + 一个任意冷饮。如下图所示

  • 选择主食

    随心配套餐主食区.jpg

  • 选择冷饮

    随心配套餐冷饮区.jpg

添加到购物车后,我们可以看到该套餐详情

套餐详情.jpg

2. 代码演示

  • 新建套餐抽象接口Meal,以及实现该接口的随心配1+1套餐SuiXinPeiMeal

    ```java
    public interface Meal {

    // 套餐价格
    Float getCost();
    
    // 套餐详情
    void order();
    

    }

public class SuiXinPeiMeal implements Meal{

  // 主食
  private Food food;

  // 冷饮
  private ColdDrink coldDrink;

  // 省略get、set方法...

  // 套餐价格
  @Override
  public Float getCost() {
      return 5F;
  }

  // 套餐详情
  @Override
  public void order() {
      System.out.println("随心配1+1套餐:");
      System.out.println("主食:" + food.getName() + ",单价:" + food.getCost());
      System.out.println("冷饮:" + coldDrink.getName() + ",单价:" + coldDrink.getCost());
      System.out.println("套餐价格:" + getCost());
  }

}


- 新建一个随心配1+1套餐的创建者`SuiXinPeiMealBuilder`:

  ```java
  public class SuiXinPeiMealBuilder {

      private Food food;
      private ColdDrink coldDrink;
      // 向套餐中添加主食
      public void addFood(Food food) {
          this.food = food;
      }
      // 向套餐中添加冷饮
      public void addColdDrink(ColdDrink coldDrink) {
          this.coldDrink = coldDrink;
      }

      // 创建套餐
      public Meal build() {
          if (food == null) {
              throw new RuntimeException("请选择一个主食");
          }
          if (coldDrink == null) {
              throw new RuntimeException("请选择一个冷饮");
          }

          SuiXinPeiMeal meal = new SuiXinPeiMeal();
          meal.setFood(food);
          meal.setColdDrink(coldDrink);
          return meal;
      }
  }
  • 新建单品抽象接口SingleProduct

    public interface SingleProduct {
         
         
        // 单品名称
        String getName();
        // 单品价格
        Float getCost();
    }
    
  • 新建主食抽象接口Food、及其实现类Chicken鸡块、Fries薯条、Hamburger汉堡

    public interface Food extends SingleProduct {
         
         
    }
    
    public class Chicken implements Food{
         
         
        @Override
        public String getName() {
         
         
            return "鸡块";
        }
    
        @Override
        public Float getCost() {
         
         
            return 13F;
        }
    }
    
    public class Fries implements Food{
         
         
        @Override
        public String getName() {
         
         
            return "薯条";
        }
    
        @Override
        public Float getCost() {
         
         
            return 10F;
        }
    }
    
    public class Hamburger implements Food {
         
         
    
        @Override
        public String getName() {
         
         
            return "汉堡";
        }
    
        @Override
        public Float getCost() {
         
         
            return 15F;
        }
    }
    
  • 新建冷饮抽象接口ColdDrink、及其实现类CocaCola可乐、NoSugarCola无糖可乐、Sprite雪碧

    public interface ColdDrink extends SingleProduct {
         
         
    }
    
    public class CocaCola implements ColdDrink{
         
         
        @Override
        public String getName() {
         
         
            return "可乐";
        }
    
        @Override
        public Float getCost() {
         
         
            return 3.8F;
        }
    }
    
    public class NoSugarCola implements ColdDrink {
         
         
        @Override
        public String getName() {
         
         
            return "无糖可乐";
        }
    
        @Override
        public Float getCost() {
         
         
            return 5.0F;
        }
    }
    
    public class Sprite implements ColdDrink {
         
         
        @Override
        public String getName() {
         
         
            return "雪碧";
        }
    
        @Override
        public Float getCost() {
         
         
            return 8F;
        }
    }
    
  • main()方法中进行套餐模拟

    public static void main(String[] args) {
         
         
        // 套餐:鸡块+可乐
        SuiXinPeiMealBuilder builder1 = new SuiXinPeiMealBuilder();
        // 选择鸡块
        builder1.addFood(new Chicken());
        // 选择可口可乐
        builder1.addColdDrink(new CocaCola());
        // 创建订单
        Meal meal1 = builder1.build();
        // 输出订单详情
        meal1.order();
    
        System.out.println("==============================================");
    
        // 套餐:汉堡+雪碧
        SuiXinPeiMealBuilder builder2 = new SuiXinPeiMealBuilder();
        builder2.addFood(new Hamburger());
        builder2.addColdDrink(new Sprite());
        Meal meal2 = builder2.build();
        meal2.order();
    }
    

3. 演示结果

运行上述代码,结果如下

演示结果.jpg

四、优缺点

  • 优点
    • 对象的创建过程与其细节表示分离,即解耦。
  • 缺点:
    • 产生多余的建造者Builder类,且每当添加一种套餐,就需要多写一个对应的套餐建造者类。
    • 建造者与对象之间耦合,当修改对象结构时,建造者也要修改。
    • 可读性相对较差。

五、送给读者

  • 在非必要的情况下,业务代码中不建议使用该设计模式,没有性能上的优化却导致可读性变差,属于炫技型设计模式。
  • 如果本文对你有所帮助,别忘了安排博主一顿麦当劳随心配1+1套餐哦。




纸上得来终觉浅,绝知此事要躬行。

————————我是万万岁,我们下期再见————————

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