9

我有一个(Java)类,其中包含许多实例字段(其中许多是可选的)。我希望所有字段(因此类)都是不可变的。所以,我想使用构建器模式来构建类的实例。

我可以配置 myBatis 以使用 Builder 模式创建类的实例吗?我知道我可以让 myBatis 返回一个地图并使用该地图在我的代码中构建实例。但是,我正在寻找一种配置此映射(或使用某种约定)的方法,类似于如何通过使用 Java Bean 和构造函数来创建实例。

编辑(包括一个例子)

这是一个例子:

package com.example.model;

// domain model class with builder
public final class CarFacts {

    private final double price;
    private final double numDoors;
    private final String make;
    private final String model;
    private final String previousOwner;
    private final String description;

    public static class Builder {
        // required params
        private final double price;
        private final String make;
        private final String model;

        // optional params
        private final String previousOwner;
        private final String description;
        private final double numDoors;

        public Builder(double price, String make, String model) {
            this.price = price;
            this.make = make;
            this.model = model;
        }

        public Builder previousOwner(String previousOwner) {
            this.previousOwner = previousOwner;
            return this;
        }
        // other methods for optional param

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

    private CarFacts(Builder builder) {
        this.price = builder.price;
        //etc.
    }
}

然后,我有一个映射器:

<!-- this doesn't work but I think h3adache suggest that I could have the resultType
be com.example.model.CarFacts.Builder and use the Builder constructor. But I'm not sure how
I would call the methods (such previousOwner(String)) to populate optional params -->

<mapper namespace="com.example.persistence.CarFactsMapper">
  <select id="selectCarFacts" resultType="com.example.model.CarFacts">
    select *
    from CarFacts
  </select>
    
</mapper>

最后,我有映射器界面:

package com.example.persistence.CarFactsMapper;

public interface CarFactsMapper {
    List<CarFacts> selectCarFacts();
}

我还希望能够通过 myBatis 使用静态工厂方法创建实例。例如:

public final class Person {

    private final String lastName;
    private final String firstName;

    private Person(String lastName, String firstName) {
        this.lastName = lastName;
        this.firstName = firstName;
    }

    public Person newInstance(String lastName, String firstName) {
        return new Person(lastName, firstName);
    }
}

具体来说,如何让 myBatis 调用 newInstance(String, String)?

4

1 回答 1

-1

您不需要使用构建器或静态工厂方法。是的,如果您试图保持不变性,这些模式肯定会有所帮助,因为可能会发生突变,我们是否应该说“在实例之间”,例如,因为构建器在调用 build() 之前被突变(以创建新的不可变实例)。

但是,不变性与给定实例的构造方式无关。它无法让我们为可变类编写构建器和静态工厂方法。在构建时,所有对象都还没有发生变异,所以真正重要的是接下来会发生什么(在建造者和工厂离开之后)。

您需要做的就是专注于类本身,并认为这个类是不可变的。常规的 myBatis 映射应该没问题 - 为自己节省编写构建器的时间。

所以 - 你的类是不可变的,是的,因为你的所有字段都是最终的,要么是原始类型,要么是字符串(在 Java 中是不可变的!)。如果您有其他非原始字段,那么您希望它们是最终的(从技术上讲,您不需要编写 final,但建议您,只要该字段实际上从未被重新分配)并且您希望他们的类一直遵循这些规则的递归。

我希望这会有所帮助,我想说明的一点是,构建器模式和工厂方法非常适合管理构造,但它们不会免费为您提供不变性,您总是需要编写构造器。

于 2013-04-06T07:17:31.663 回答