设计模式之【建造者模式】

本文通过麦当劳的标准化制作流程引入建造者模式,解释了建造者模式的原理和优点,以及与工厂模式的区别。通过煲汤的例子展示了建造者模式在代码中的应用,并提供了经典建造者模式的四个角色:Product、Builder、ConcreteBuilder和Director。文章还探讨了建造者模式在处理复杂对象创建和定制化需求时的优势,以及适用的场景。
摘要由CSDN通过智能技术生成

设计原则是指导我们代码设计的一些经验总结,也就是“心法”;面向对象就是我们的“武器”;设计模式就是“招式”。

以心法为基础,以武器运用招式应对复杂的编程问题。

为什么麦当劳那么受欢迎?

表妹:哥啊,我想吃麦当劳

我:你为啥那么喜欢吃麦当劳呢?

表妹:因为它好吃呀,而且每个门店吃的味道都差不多,不像某县小吃,每个地方吃的味道都有区别。

我:那你知道为什么嘛?

表妹:因为麦当劳有一套非常完善的工作流程,每个门店都必须遵守这套规范…

这不就是我们设计模式中的【建造者模式】嘛?


将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。

我们以煲汤为例子,我们知道,主汤料和水是煲汤必须的,配料是可放可不放的,有些人喜欢吃原汁原味,可以不放盐,有些肉比较油,那么,也可以不放油。

我们来看看具体的代码实现:

public class Soup {
   
    private static final int MAX_INGREDIENTS = 10;
    private static final int MAX_OIL = 8;
    private static final int MAX_SALT = 5;
    
    private String mainIngredient;  // 主料必须
    private String water;           // 水必须
    private int ingredients;        // 配料可选
    private int oil;                // 油可选
    private int salt;               // 盐可选
    
    public Soup(String main, String water, Integer ingredients, Integer oil, Integer salt) {
   
        if (StringUtils.isBlank(main)) {
   
            throw new IllegalArgumentException("main should not be empty");
        }
        this.mainIngredient = main;
    
        if (StringUtils.isBlank(water)) {
   
            throw new IllegalArgumentException("water should not be empty");
        }
        this.water = water;
    
        if (ingredients != null) {
   
            if (ingredients < 0) {
   
                throw new IllegalArgumentException("ingredients should not be positive");
            }
        	this.ingredients = ingredients;
    	}
        
		if (oil != null) {
   
        	if (oil < 0) {
   
            	throw new IllegalArgumentException("oil should not be positive");
        	}
        	this.oil = oil;
    	}
        
		if (salt != null) {
   
        	if (salt < 0) {
   
            	throw new IllegalArgumentException("salt should not be positive");
        	}
        	this.salt = salt;
    	}
	}
    
    // 省略get方法
}

// 今天想吃鱼头豆腐汤
Soup fishHeadTofuSoup = new Soup("鱼头", "山泉水", 10, 6, 3);

大家可以看到,这个构造函数有5个参数,参数列表太长,导致代码在可读性和易用性上都会变差。

而且这么长的参数列表,参数类型一样的都连在一起,在使用构造函数的时候,就很容易搞错各参数的顺序,传递进错误的参数值,导致非常隐蔽的bug。上面这个例子中,配料和盐都是int类型,万一我一不小心,把这两个参数的位置互换了,变成放3克的配料,放10克的盐,那还能吃嘛?

有些同学可能会说,你这个类在构造对象的时候,有些属性是可选可不选的,这些属性可以通过set()函数来设置。

是的,我们来看一下,这种方法的实现效果:

public class Soup {
   
    private static final int MAX_INGREDIENTS = 10;
    private static final int MAX_OIL = 8;
    private static final int MAX_SALT = 5;
    
    private String mainIngredient;  // 主料必须
    private String water;           // 水必须
    private int ingredients;        // 配料可选
    private int oil;                // 油可选
    private int salt;               // 盐可选
    
    public Soup(String main, String water) {
   
        if (StringUtils.isBlank(main)) {
   
            throw new IllegalArgumentException("main should not be empty");
        }
        this.mainIngredient = main;
    
        if (StringUtils.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值