设计模式演化之建造者模式

定义

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

演化

1.定义一个电脑类,并提供给外界创建它的方法,我们通常会这么做

public class Computer {
   
    private String cpu;
    private String mainboard;
    
    public Computer(String cpu) {
   
        this.cpu = cpu;
    }
  
    public Computer(String cpu, String mainboard) {
   
        this.cpu = cpu;
        this.mainboard= mainboard;
    }
    // 省略getter和setter
}

调用者创建对象时,按照规则传入参数即可。但这里依然存在些许小问题。

(1) 调用者不需要cpu,想要只传入一个mainboard参数来构建对象。如何提供相应的构造函数?你会发现这么一个简单的问题根本无法入手,因为cpu和mainboard都是String类型。单独构建时,其构造方法签名是一致的。因此无法提供单独构建mainboard。调用者只能使用代码中给出的双参数构造函数,构建对象时,不需要的参数传null。

public void build() {
   
    Computer computer = new Computer(null, "mainboard");  
}

(2) 在(1)的前提下,调用者需要知道构造方法中,每个参数的意义。如果创建时,先传mainboard,再传null,肯定会产生错误。代码的可读性也不高,以后接手的人需要先了解Computer的构造方法,才能知道这里每个传入参数的意义。

当然在仅仅只有两个的参数的时候,这两个小问题都可以忽略不计。调用处多传一个null参数,创建成本不算高。记住两个参数的意义也是小菜一碟。而且现在的开发工具都附带一定的提示功能,代码阅读也没有太大问题。

2.现在我们扩展这个电脑类,然后再考虑1中遗留的问题

public class Computer {
   
    private String cpu;
    private String mainBoard;
    private String memory;
    private String displayAdapter;
    private String networkAdapter;
    private String monitor;
    private String hdd;
    private String fdd;
    private String mouse;
    private String keyboard;
    // 省略getter和setter
}

调用者传入的参数十分灵活,可能只是其中任意的一个或几个。这个时候你会发现想要提供灵活的构造方法根本无从下手:构造参数的排列组合情况过多,当参数数量相同时,还会产生冲突。想要通过构造函数兼容所有的情况,就只能提供一个包含全部属性的构造函数了。

public Computer(String cpu, String mainBoard, String memory, String displayAdapter, String networkAdapter, String monitor, String hdd, String fdd, String mouse, String keyboard) {
   
        this.cpu = cpu;
        this.mainBoard = mainBoard;
        this.memory = memory;
        this.displayAdapter = displayAdapter;
        this.networkAdapter = networkAdapter;
        this.monitor = monitor;
        this.hdd = hdd;
        this.fdd = fdd;
        this.mouse = mouse;
        this.keyboard = keyboard;
    }

这个构造函数有10个参数,调用者要知道每个位置对应的参数,才能把自己的参数传到指定位置,对于不需要的参数还要传入null。此时创建一个参数的成本已经很高了,而且极易出错,这点在构造函数仅有三四个参数时就有可能出现了,更何况是10个乃至更多参数。即便是费劲写好了构造过程,换个人来阅读这段代码时,理解起来也会很有难度。

总结,在创建一个多参数类的对象时,会存在以下问题
(1) 定义者只能提供有限的构造方法
(2) 调用者需要充分了解类的构造方法,并选择自己需要的。
(3) 调用者创建对象成本较高,还会产生冗余代码。
(4) 调用者对于构造方法的使用容易出错
(5) 调用处的代码可读性不高

3.考虑前面所说的问题,我们在定义类仅指定默认构造方法和关键参数的构造方法,让调用者自己手动调用setter去设置值。使用这种方式倒是无需定义繁琐的构造方法,调用者也可以灵活控制参数而无需过多了解构造方法,并且可以通过setter的方法名清晰的表达设置的意图,提高代码的可读性。这也是我们平时创建一个多参数对象的常见写法了,大多数情况下都是这么做的,也很少出问题。因为我们创建的所谓复杂对象,仅仅是参数多点罢了。

public void build() {
   
    Computer computer = new Computer();
    computer.setCpu(&
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值