Đây chỉ là đề xuất bán nghiêm túc, nhưng chúng tôi có thể sửa đổi mikera's answer thành an toàn.
Giả sử chúng ta có:
public class A {
private final String foo;
private final int bar;
private final Date baz;
}
Sau đó chúng ta viết:
public abstract class AProperty<T> {
public static final AProperty<String> FOO = new AProperty<String>(String.class) {};
public static final AProperty<Integer> BAR = new AProperty<Integer>(Integer.class) {};
public static final AProperty<Date> BAZ = new AProperty<Date>(Date.class) {};
public final Class<T> propertyClass;
private AProperty(Class<T> propertyClass) {
this.propertyClass = propertyClass;
}
}
Và:
public class APropertyMap {
private final Map<AProperty<?>, Object> properties = new HashMap<AProperty<?>, Object>();
public <T> void put(AProperty<T> property, T value) {
properties.put(property, value);
}
public <T> T get(AProperty<T> property) {
return property.propertyClass.cast(properties.get(property));
}
}
Tín đồ của các mẫu thiết kế tiên tiến và/hoặc tối nghĩa thủ thuật Java sẽ nhận ra đây là một container không đồng nhất an toàn. Chỉ cần biết ơn tôi đã không sử dụng getGenericSuperclass()
là tốt.
Sau đó, trở lại trong lớp mục tiêu:
public A(APropertyMap properties) {
foo = properties.get(AProperty.FOO);
bar = properties.get(AProperty.BAR);
baz = properties.get(AProperty.BAZ);
}
này đều sử dụng như thế này:
APropertyMap properties = new APropertyMap();
properties.put(AProperty.FOO, "skidoo");
properties.put(AProperty.BAR, 23);
A a = new A(properties);
Chỉ cần cho lulz, chúng tôi thậm chí có thể cung cấp bản đồ một giao diện thông thạo:
public <T> APropertyMap with(AProperty<T> property, T value) {
put(property, value);
return this;
}
Cho phép người gọi viết:
A a = new A(new APropertyMap()
.with(AProperty.FOO, "skidoo")
.with(AProperty.BAR, 23));
Có rất nhiều cải tiến nhỏ mà bạn có thể thực hiện cho việc này. Các loại trong AProperty
có thể được xử lý một cách trang nhã hơn. APropertyMap
có thể có một nhà máy tĩnh thay vì một nhà xây dựng, cho phép một phong cách mã thông thạo hơn, nếu bạn đang vào loại điều đó. APropertyMap
có thể phát triển phương thức build
gọi hàm tạo của A
, về cơ bản biến nó thành trình tạo.
Bạn cũng có thể thực hiện một số đối tượng này thay vì chung chung hơn. AProperty
và APropertyMap
có thể có các lớp cơ sở chung đã thực hiện các bit chức năng, với các lớp con rất đơn giản A
-specific.
Nếu bạn cảm thấy đặc biệt là doanh nghiệp và đối tượng miền của bạn là thực thể JPA2, thì bạn có thể sử dụng các thuộc tính siêu mô hình làm đối tượng thuộc tính. Điều này khiến map/builder làm việc nhiều hơn một chút, nhưng nó vẫn khá đơn giản; tôi có một trình xây dựng chung làm việc trong 45 dòng, với một phân lớp cho mỗi thực thể có chứa một phương thức một dòng.
Bạn thậm chí không cần getters trong builder của bạn, và constructor của A có thể được tư nhân. Điều này cũng cho phép kiểm tra các tham số trong phương thức build() thay vì hàm tạo. –
Đúng. Tôi coi việc làm ctor của A là riêng tư. Đó có lẽ là sạch hơn. –
Một ưu điểm khác là người xây dựng có thể chọn trả về một thể hiện của A, ABis hoặc ATer (Abis và Ater là các lớp con của A), tùy thuộc vào các tham số. –