一起谈谈设计模式(二):建造者模式

本文详细介绍了建造者模式的概念及其在Java中的实际应用,通过一个炒菜的例子展示了如何创建产品对象、定义建造者接口及其实现、以及指挥者的角色。在实际开发中,特别是在对象转换场景下,建造者模式可以有效地避免冗长的转换代码,提高代码的可读性和可维护性。例如,从DTO到实体对象的转换过程中,利用内部建造者模式可以简洁高效地完成转换任务。
摘要由CSDN通过智能技术生成

建造者模式是一种常用的设计模式,你可能每时每刻都在用只是你没有察觉到。比如我们常用的lambok内的@Builder注解,就是使用了建造者模式,业务代码中只要调用.builder方法,然后设置属性,最后调用.build就得到了最终的目标对象。这篇文章首先讲建造者模式内的几种角色,以及他们之间是如何配合完成一个对象的创建,最后会将lambok实现建造者模式的代码写出来。这种代码其实很简单,在日常开发过程中都是可以使用的。

建造者模式

在建造者模式中有几个重要的角色,一个是指挥者、一个是建造者,最后就是具体需要建造的对象。

指挥者:就是指挥建造者来实现一系列的流程建造一个对象。

建造者:通过指挥者的调度,依次执行逻辑代码,最终一步一步的将产品建造出来。

产品对象:也就是需要建造的对象。

概念大概知道了,下面通过代码体现出来。

产品对象

这里以炒菜为例,现在客户分别需要两个当地特色菜品,其中醋溜土豆丝只有厨师张三会做,油焖茄子只有李四会做。客户来了以后和点菜的服务员说了,他就想吃这两样特色菜,此时服务员将菜单交给大厨师傅,师傅开始指挥张三和李四开始做菜。

public class Product{
    
}
//醋溜土豆丝
public class Potato extends Product{
    private Integer salt;
    private Integer oil;
    public void setSalt(Integer salt){
        this.salt = salt;
    }
    public void setOil(Integer oil){
        this.oil = oil;
    }
}
//油焖茄子
public class Eggplant extends Product{
    private Integer salt;
    private Integer oil;
    public void setSalt(Integer salt){
        this.salt = salt;
    }
    public void setOil(Integer oil){
        this.oil = oil;
    }
}

需要创建的两个产品有了,但是还要具体的建造者。

建造者
public class Builder{
    void addSalt();
    void addOil();
    Product get();
}
//醋溜土豆丝建造者
public class PotatoBuilder implements Builder{
    private Potato potato;
    public void addSalt(){
        potato.addSalt(1);
    }
    public void addOil(){
        potato.addOil(20);
    }
}
//油焖茄子建造者
public class EggplantBuilder implements Builder{
    private Eggplant eggplant;
    public void addSalt(){
        potato.addSalt(3);
    }
    public void addOil(){
        potato.addOil(50);
    }
}

建造者有了,需要一个指挥者,这里的指挥者就相当于张三和李四的大厨师傅。

//指挥者
public class Director{
    public void doit(Builder builder){
        //指挥做菜
        builder.addSalt();
        buiilder.addOil();
    }
}

传上菜单,开始做菜。

public class Main{
    public static void main(String[] args){
        Builder potatoBuilder = new PotatoBuilder();
        Builder eggplantBuilder = new EggplantBuilder();
        Director director = new Director();
        //醋溜土豆丝出锅
        director.doit(potatoBuilder);
        Potato  potato= (Potato)potatoBuilder.get();
        //油焖茄子出锅
        director.doit(eggplantBuilder);
        Eggplant eggplant = (Potato)EggplantBuilder.get();
    }
}

整个建造者实现的过程是如上代码,加上上面对建造者模式的说明,应该不难理解。三个角色在其中各司其职,最终完成产品的建造过程。体现到UML图就是如下:

在这里插入图片描述

一般在什么时候能用到这个呢,之前在说mybatis源码的时候,就用到建造者模式,这个说起来就点多了,为了更好的说明清楚,来说一个实际开发中能够经常用到的。

前端传入的参数一般都是用DTO来接收,但是最终入库的时候是需要转换成对应的实体对象,恰恰DTO中接收参数的字段和实际实体类的字段名有出入,这个转换过程就可以用到建造者模式。因为直接在业务代码中写冗长的转换代码实在是不太妥。

在实体类中创建一个建造者内部类,然后将DTO传入给建造者,有建造者完成构建并给出对应的实体对象。

建造者的实际运用

接上面的DTO的介绍来写一个对象转换中使用到建造者模式。

public class User{
    private String userName;
    private String mobile;
    private Integer age;
    private String nickName;
    //getter……
    //setter……
    //生成建造者对象
    public Builder builder(){
        return new Builder();
    }
    //建造者
    public class Builder{
        //建造者构建目标对象user
        public User build(UserDTO userDto){
            User user  = new User();
            user.setUserName(userDto.getName());
            user.serMobile(userDto.getPhone());
            user.setAge(userDto.getAge());
            user.setNickName(userDto.getNickName());
            return user;
        }
    }
}

此时业务代码中只要一行代码就可以。如下:

User user = User.builder().build(userDto);

很简单的一种使用方式,也是很有高效的,业务代码中用到这种封装的地方很多,就避免了重复代码的出现。也许你可以说其实可以直接在业务代码中抽离一个公共的方法完成,但是想比较而言,这种方式不好。如果抽离方法可能会比较麻烦,需要写在公共的包内,然后公共的包又要引入dao层对应的包,很容易出现循环引用,设计上也不是很合理。如果直接由内部建造者模式实现,减少的麻烦不止一点。

另外要说明的一点就是,实际在开发中转换用的比较多的是dozer,保证两个类的字段名相同,然后用dozer来实现转换。又或者通过配置文件来配置两个类字段的对应关系。但是dozer这种使用方式是很慢的,相对于这种建造者模式来说。可以通过debug断点的方式测试一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿洞晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值