23种设计模式(4):建造者模式

1.概念

定义:建造者模式是把一个物体的构造过程与其本身进行分离,使得相同的构造过程可以创建不同的物体,简而言之,就是构造过程复用

想象一下我们玩角色扮演类游戏的时候,刚开始电脑会让你创建角色,比如选择人物的职业、头发颜色、性别,最后输入一个骚气的昵称,这个创建的过程就算完成了!

2.为什么要用这个建造者模式呢

答:它是一种创建对象的软件设计模式,旨在提高对象构造器的伸缩性

不用这个模式,我们的对象伸缩性瓶颈是哪里呢?看下面的代码就会明白:

public Hero(Profession profession, String name) {
}

如您所见,构造函数参数的数量如果再增加,那么很快就会失控,因为同样类型的参数,我们可能难以理解参数的排列。另外,如果将来想添加更多选项,则此参数列表可能会继续增长。这也被称为伸缩构造函数反模式

3.程式范例

还是以游戏中创建英雄的例子来说吧,先来完成我们英雄的一些初始化属性。

/**
 * 职业的枚举类
 *
 * @author suvue
 * @date 2020/1/12
 */
public enum Profession {

    /**
     * 战士
     */
    WARRIOR,

    /**
     * 刺客
     */
    THIEF,
    /**
     * 法师
     */
    MAGE,
    ;

    @Override
    public String toString() {
        return name().toLowerCase();
    }
}

下面是英雄的头发颜色枚举。

/**
 * 头发颜色
 *
 * @author suvue
 * @date 2020/1/12
 */
public enum HairColor {
    /**
     * 红发
     */
    RED,
    /**
     * 棕发
     */
    BROWN,
    /**
     * 黑发
     */
    BLACK,
    ;

    @Override
    public String toString() {
        return name().toLowerCase();
    }

}

下面是英雄持有的武器枚举了。

import lombok.Data;

/**
 * 英雄
 *
 * @author suvue
 * @date 2020/1/12
 */
@Data
public class Hero {
    private final HairColor hairColor;
    private final Profession profession;
    private final Weapon weapon;
    private final String name;

    /**
     * 我们传进来一个通用的建造器
     */
    public Hero(Builder builder) {
        this.hairColor = builder.hairColor;
        this.profession = builder.profession;
        this.weapon = builder.weapon;
        this.name = builder.name;
    }

    /**
     * 这是一个静态内部类,我们来实现这个通用建造器
     */
    public static class Builder {
        private HairColor hairColor;
        private final Profession profession;
        private Weapon weapon;
        private final String name;

        /**
         * 建造器的构造函数 我们要求职业和昵称必填
         */
        public Builder(Profession profession, String name) {
            if (profession == null || name == null) {
                throw new IllegalArgumentException("初始化参数为空");
            }
            this.profession = profession;
            this.name = name;
        }

        public Builder withHairColor(HairColor hairColor) {
            this.hairColor = hairColor;
            return this;
        }

        public Builder withWeapon(Weapon weapon) {
            this.weapon = weapon;
            return this;
        }

        public Hero build() {
            return new Hero(this);
        }


    }

}

我们来看看具体是怎么使用的吧

public class Client {
    public static void main(String[] args) {
        //创建一个拿着法杖的红发魔法师角色
        Hero mage = new Hero
                .Builder(Profession.MAGE, "法师")
                .withHairColor(HairColor.RED)
                .withWeapon(Weapon.ROD)
                .build();
        System.out.println(mage.toString());

        //创建一个拿着剑的黑发战士角色
        Hero warrior = new Hero.Builder(Profession.WARRIOR, "战士")
                .withHairColor(HairColor.BLACK)
                .withWeapon(Weapon.SWORD)
                .build();
        System.out.println(warrior.toString());
    }
}

创建过程是不是很简单呢,而且以后要是扩展的话,直接在Hero类中加一个类似于withWeapon()的方法就行啦

前辈们总结的经验,都乃是精髓呀!

4.建造者模式在框架中的使用

4.1JDK1.8源码中的建造者模式

StringBuilder与StringBuffer的父抽象类:AbstractStringBuilder 我们截取一部分关键源码看一下。

 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
4.2 spring中的建造者模式

摘选 BeanDefinitionBuilder 类的部分源码。

package org.springframework.beans.factory.support;
public final class BeanDefinitionBuilder {
    //获取builder对象的静态方法
    public static BeanDefinitionBuilder genericBeanDefinition() {
		return new BeanDefinitionBuilder(new GenericBeanDefinition());
	}
    
    public BeanDefinitionBuilder setParentName(String parentName) {
		this.beanDefinition.setParentName(parentName);
		return this;
	}
    
    public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {
		this.beanDefinition.setFactoryMethodName(factoryMethod);
		return this;
	}
    
    public BeanDefinitionBuilder setFactoryMethodOnBean(String factoryMethod, String factoryBean) {
		this.beanDefinition.setFactoryMethodName(factoryMethod);
		this.beanDefinition.setFactoryBeanName(factoryBean);
		return this;
	}
    //可以有很多个set方法灵活性的为属性赋值
    //...
    
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值