问题描述
我非常好奇为java bean提供不可变性的可能性(这里的bean是指一个空的构造函数为成员提供getters和setter的类)。显然这些类是不可变的,并且它们用于从数据层传输值这似乎是一个真正的问题。
I am very curious about the possibility of providing immutability for java beans (by beans here I mean classes with an empty constructor providing getters and setters for members). Clearly these classes are not immutable and where they are used to transport values from the data layer this seems like a real problem.
这个问题的一种方法已经在这里提到StackOverflow称为C#中的不可变对象模式,其中对象在完全构建后冻结。我有一个替代方法,并真的想听到人们对它的意见。
One approach to this problem has been mentioned here in StackOverflow called "Immutable object pattern in C#" where the object is frozen once fully built. I have an alternative approach and would really like to hear people's opinions on it.
模式涉及两个类Immutable和Mutable,其中mutable和immutable都实现一个接口, -mutating bean方法。
The pattern involves two classes Immutable and Mutable where Mutable and Immutable both implement an interface which provides non-mutating bean methods.
例如
public interface DateBean {
public Date getDate();
public DateBean getImmutableInstance();
public DateBean getMutableInstance();
}
public class ImmutableDate implements DateBean {
private Date date;
ImmutableDate(Date date) {
this.date = new Date(date.getTime());
}
public Date getDate() {
return new Date(date.getTime());
}
public DateBean getImmutableInstance() {
return this;
}
public DateBean getMutableInstance() {
MutableDate dateBean = new MutableDate();
dateBean.setDate(getDate());
return dateBean;
}
}
public class MutableDate implements DateBean {
private Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public DateBean getImmutableInstance() {
return new ImmutableDate(this.date);
}
public DateBean getMutableInstance() {
MutableDate dateBean = new MutableDate();
dateBean.setDate(getDate());
return dateBean;
}
}
这种方法允许使用反射通过惯例),也允许我们在最近的机会转换为不可变的变体。不幸的是,每个bean显然有大量的样板。
This approach allows the bean to be constructed using reflection (by the usual conventions) and also allows us to convert to an immutable variant at the nearest opportunity. Unfortunately there is clearly a large amount of boilerplate per bean.
我很感兴趣听到别人对这个问题的解决方法。 (我不能提供一个好的问题,可以回答而不是讨论:)
I am very interested to hear other people's approach to this issue. (My apologies for not providing a good question, which can be answered rather than discussed :)
推荐答案
代理模式 - 使用一个必须在构造函数中指定的单个DateBean成员创建一个ImmutableDate类:
I think I'd use the delegation pattern - make an ImmutableDate class with a single DateBean member that must be specified in the constructor:
public class ImmutableDate implements DateBean
{
private DateBean delegate;
public ImmutableDate(DateBean d)
{
this.delegate = d;
}
public Date getDate()
{
return delegate.getDate();
}
}
如果我需要在DateBean上强制不变性d ,我只是新的ImmutableDate(d)就可以了。我可以聪明,并确保我没有委派代表,但你得到的想法。这避免了客户端试图将其转换为可变的问题。这很像JDK使用Collections.unmodifiableMap()等(在这些情况下,但是,突变功能仍然必须实现,并编码为抛出一个运行时异常。如果你有一个基本接口没有mutators)。
If ever I need to force immutability on a DateBean d, I just new ImmutableDate(d) on it. I could have been smart and made sure I didn't delegate the delegate, but you get the idea. That avoids the issue of a client trying to cast it into something mutable. This is much like the JDK does with Collections.unmodifiableMap() etc. (in those cases, however, the mutation functions still have to be implemented, and are coded to throw a runtime exception. Much easier if you have a base interface without the mutators).
再一次,这是一个繁琐的样板代码,但它是一个好东西,如Eclipse可以自动生成为您只需点击几下鼠标。
Yet again it is tedious boilerplate code but it is the sort of thing that a good IDE like Eclipse can auto-generate for you with just a few mouse clicks.
如果这是你最终对很多域对象做的事情,你可能需要考虑使用动态代理,甚至AOP。这将是相对容易的,然后为任何对象构建一个代理,委托所有的get方法,并适当地陷阱或忽略设置的方法。
If it's the sort of thing you end up doing to a lot of domain objects, you might want to consider using dynamic proxies or maybe even AOP. It would be relatively easy then to build a proxy for any object, delegating all the get methods, and trapping or ignoring the set methods as appropriate.
这篇关于Java中的不可变bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!