Builder Pattern--构造者模式实例

当我在学习领域驱动设计(DDD)以及Effective Java的时候,发现构造者模式非常有用。从阅读方式及性能原因分析如下:

第一:在领域驱动设计中,很多时候需要给领域对象赋值,那么当一个领域对象的属性域(Field字段)内容较多,那么赋值的时候,怎么达到轻松易读,意思表达明确,语句简单?

第二:怎么通过对对象的赋值就能知道对象有哪些属性,以及对应属性的名称和含义?

构造者模式能很好的解决上面问题,回到构造者模式定义上:

构造柱模式能将复杂对象的构造过程与其表示分开,以便同样的构造过程可以创建不同的对象呈现,并且这种设计模式能带来一个副作用:我们可以避免与构造函数构造一个参数较多对象相关的错误,考虑下面实例:

public class Employee {
      private int id;
      private String name;
      private String department;
      private String address;
      private String phone;
      private String mobile;

      public Employee(String name, String deptt, String address,
                  String phone, String mobile) {
            super();
            this.id = generateId();
            this.name = name;
            this.deptt = deptt;
            this.address = address;
            this.phone = phone;
            this.mobile = mobile;
      }

      private int generateId(){
            int id = 0; //Generate a unique id here with some mechanism
            return id;
      }
}

你能发现问题吗??

这个Employee的构造函数需要开发者传入name、deptt、address等,并且按照特定的顺序,并且所有的参数都是String类型,所以在传入参数时候,开发者还必须记住或者查找文档中所有参数的意义。想象一下当有超过10个参数的情况。这在这种情况下非常麻烦。

我们如何让使用这个类的开发人员更轻松?一种方式可能是为每个属性提供默认的构造函数和setter方法。我用这种方法看到了一些问题,即:

  1. 如果我的类不应该有默认的构造函数,即我们无法想象没有姓名,部门,地址,电话或移动设备的员工。一个参数可能是我们有一个具有强制属性的构造函数。如果强制性属性列表本身太长,我们还是需要知道所以属性含义,问题依然是属性太多而不知具体含义。但是,如果强制性参数的数量不是太大,那么我们可以使用这种方法。
  2. 如果我们使用setter,有时候我们创建了员工对象,但在逻辑意义上并不完整,即我们仍在设置属性。当有多个线程试图访问该对象时,该对象的不一致状态可能会导致问题。

接下来我们尝试用构造者模式来解决:

然而,在我们看到它之前,在实施过程中需要注意几点。

  • Employee类的构造函数必须是私有的,确保没有人可以使用有问题的构造函数创建对象,也阻止了开发者直接用构造函数创建对象。
  • Builder类是一个内联类。为什么是内联类?因为我们在原Employee类中不提供公共的setter方法,当时构造器却需要访问Employee的私有属性。所以Builder只能是Employee的内联类。

public class Employee {
    private int id;
    private String name;
    private String department;
    private String address;
    private String phone;
    private String mobile;

    private Employee(String name, String deptt, String address,
        String phone, String mobile) {
        super();
        this.id = generateId();
        this.name = name;
        this.department = deptt;
        this.address = address;
        this.phone = phone;
        this.mobile = mobile;
    }

    private int generateId() {
        //Generate an id with some mechanism
        int id = 0;
        return id;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", department=" +
            department + ", address=" + address + ", phone=" + phone + ", mobile=" + mobile + "]";

    }

    static public class Builder {
        private int id;
        private String name;
        private String department;
        private String address;
        private String phone;
        private String mobile;
        public Builder() {}

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder department(String deptt) {
            this.department = deptt;
            return this;
        }

        public Builder address(String address) {
            this.address = address;
            return this;
        }

        public Employee build() {
            Employee emp = new Employee(name, department, address, phone, mobile);
            return emp;
        }
    }
}

其中注意:

1、Employee的构造函数是私有的。

2、Builder的类为static的。

调用的写法如下:

public class TestMain {
    public static void main(String[] args) {
        Employee.Builder builder = new Employee.Builder();
        Employee emp = builder.address("my address").department("my deptt").name("my name").build();
        System.out.println("Employee created is " + emp);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值