我想解決這樣的問題。我有一些抽象類和一個帶有回傳該類實體的設定器的具體類:
@MappedSuperclass
public abstract class BaseEntity implements Serializable {
private Integer id;
public Integer getId() {
return id;
}
public BaseEntity setId(Integer id) {
this.id = id;
return this;
}
}
下一個摘要:
@MappedSuperclass
public abstract class NamedEntity extends BaseEntity {
private String name;
public String getName() {
return name;
}
public NamedEntity setName(String name) {
this.name = name;
return this;
}
}
最后是一個具體的類:
@Entity
public class Person extends NamedEntity {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
我想使用這種構建器,但在當前設定中,由于父設定器的回傳型別不同,它無法正常作業
public Person build() {
Person person = new Person()
.setId(1); //return BaseEntity instead of Person
.setName("name") //returns NamedEntity instead of Person
.setAddress("foo"); //return Person!
return person;
}
當然有一個覆寫設定器的解決方法,但是....可以使用泛型以其他方式完成嗎?
@Override
public Person setId(Integer id) {
super.setId(id);
return this;
}
@Override
public Person setName(String name) {
super.setName(name);
return this;
}
uj5u.com熱心網友回復:
您可以使用與 enums ( ) 相同的技巧Enum,它是子類的泛型型別引數。
@MappedSuperclass
public abstract class BaseEntity<E extends BaseEntity<E>> implements Serializable {
private Integer id;
public Integer getId() {
return id;
}
public E setId(Integer id) {
this.id = id;
return this;
}
}
@MappedSuperclass
public abstract class NamedEntity<E extends NamedEntity<E>> extends BaseEntity<E> {
private String name;
public String getName() {
return name;
}
public E setName(String name) {
this.name = name;
return this;
}
}
對于 Person 的子類,您無需繼續使用此模式。
@Entity
public class Person extends NamedEntity<Person> {
private String address;
public String getAddress() {
return address;
}
public Person setAddress(String address) {
this.address = address;
return this;
}
}
現在你可以做_
Person einstein = new Person()
.setId(76)
.setName("Albert")
.setAddress("Princeton, New Jersey");
另一種選擇是Builder模式,但是它具有相同的繼承問題,并且您最終可能會得到 *.Builder 類從父 Builder 類繼承。
我什至會說不值得這個樣板代碼,只是為了一個流暢的 API(鏈式呼叫)。例如,criteria API 幾乎不需要使用創建的物件,并且 setter 的傳遞值也必須來自某些代碼。
setter 也意味著類是可變的。如果大多數欄位都是不可變的,那就更好了。使用物體類是不切實際的,但是 setter 是一個丑陋的初始化。盡可能使用沒有設定器的構造器/構建器。
uj5u.com熱心網友回復:
您可以通過引入具有一組自回傳方法(即回傳 的實體)的嵌套類來實作Builder 模式,這些方法可以以流暢的方式鏈接。BuilderBuilder
方法Builder.build()應該回傳一個Person.
請注意,您的物體的設定者可以是void.
這就是實作的樣子:
public class Person extends NamedEntity {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public static class Builder {
private Person person;
public Builder() {
this.person = new Person();
}
public Builder name(String name) {
person.setName(name);
return this;
}
public Builder address(String address) {
person.setAddress(address);
return this;
}
public Builder id(Integer id) {
person.setId(id);
return this;
}
public Person build() {
return person;
}
}
}
使用示例:
Person person = new Person.Builder()
.name("Alice")
.address("Wonderland")
.id(1)
.build();
筆記:
- 可能有多種方法可以獲取
Builder. 您可以在Person類中引入一個builder()回傳新的靜態方法Builder,或者類似的靜態方法withName(String),withId(Integer)也可能很方便(為了獲得靈感,請查看 Spring Security 中的類User)。 - 當使用不可變物件撥號時,
Builder類應該復制目標類的所有欄位,而不是保留對目標物件的參考。在這種情況下,方法build()將負責構造目標型別的實體。
uj5u.com熱心網友回復:
感謝我知道構建器模式的所有建議,但在這種特殊情況下,與覆寫方法相同的解決方法setId和setName
這里的要點是:該setId方法可能會回傳子類的實體,該方法是從中呼叫的
假設我想將一個復雜的物件放到我的構建器中(為什么不呢?):
public class Person extends NamedEntity {
private String address;
... getters/setters
public Builder builder() {
return new Builder();
}
public final static class Builder {
private final Person person;
private Long id;
private String name;
private String address;
private Builder() {
this.person = new Person();
}
public Builder withId(Long id) {
person.setId(id);
return this;
}
..... other setters
public Builder withDto(PersonDTO dto) {
person
.setId(dto.getId())
.setName(dto.getName())
.setAddress(dto.getAddress()
}
public Person build() {
return person;
}
}
}
你可能會猜到person.setIdBaseEntity 的回傳實體
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/511213.html
標籤:爪哇仿制药遗产
