针对一些数据对象,我们更强调的是这个对象的值而不是这个对象本身的时候,就可以使用值对象模式。意思就是两个对象判定相等的时候应该是两个对象的"值"相等,而不是它俩必须是同一个对象。在编写值对象模式的时候,应该注意以下几点(以java为例):
1、必须重写equals()、hashCode(),且重写的原则是两个对象的"值"相等的化,equal()和hashCode()必然相等。
2、值对象一般不可修改,因此成员变量应用final修饰。
3、应该提供getters方法获取成员变量的值。
4、两个对象使用equal()比较而不是==
类图:
代码:
/**
* HeroStat is a value object
*
* {@link http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html}
*/
public class HeroStat {
// Stats for a hero
private final int strength;
private final int intelligence;
private final int luck;
// All constructors must be private.
private HeroStat(int strength, int intelligence, int luck) {
super();
this.strength = strength;
this.intelligence = intelligence;
this.luck = luck;
}
// Static factory method to create new instances.
public static HeroStat valueOf(int strength, int intelligence, int luck) {
return new HeroStat(strength, intelligence, luck);
}
public int getStrength() {
return strength;
}
public int getIntelligence() {
return intelligence;
}
public int getLuck() {
return luck;
}
/*
* Recommended to provide a static factory method capable of creating an instance from the formal
* string representation declared like this. public static HeroStat parse(String string) {}
*/
// toString, hashCode, equals
@Override
public String toString() {
return "HeroStat [strength=" + strength + ", intelligence=" + intelligence
+ ", luck=" + luck + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + intelligence;
result = prime * result + luck;
result = prime * result + strength;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
HeroStat other = (HeroStat) obj;
if (intelligence != other.intelligence) {
return false;
}
if (luck != other.luck) {
return false;
}
if (strength != other.strength) {
return false;
}
return true;
}
// The clone() method should not be public. Just don't override it.
}
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/**
* This practice creates three HeroStats(Value object) and checks equality between those.
*/
public static void main(String[] args) {
HeroStat statA = HeroStat.valueOf(10, 5, 0);
HeroStat statB = HeroStat.valueOf(10, 5, 0);
HeroStat statC = HeroStat.valueOf(5, 1, 8);
LOGGER.info(statA.toString());
LOGGER.info("Is statA and statB equal : {}", statA.equals(statB));
LOGGER.info("Is statA and statC equal : {}", statA.equals(statC));
}
}