# 定义不可变对象的策略
以下规则定义了创建不可变对象的简单策略。不是所有记录为“不可变”的类都遵循这些规则。 这并不一定意味着这些课程的创作者是马虎的 - 他们可能有充分的理由相信他们的课程在施工后永远不会改变。 然而,这种策略需要复杂的分析,而不适合初学者。
- 不提供“setter”方法 - 修改字段引用的字段或对象的方法。
- 使用
final
和private
域。 - 不允许子类覆盖方法。最简单的方法是将类声明为
final
。更复杂的方法是private
在工厂方法中使构造函数和构造实例。 - 如果实例字段包含对可变对象的引用,则不允许更改这些对象:
- 不提供修改可变对象的方法。
- 不要共享对可变对象的引用。不要存储对传递给构造函数的外部可变对象的引用; 如有必要,请创建副本,并存储对副本的引用。同样,在必要时创建内部可变对象的副本,以避免在方法中返回原件。
应用此策略可以 SynchronizedRGB 执行以下步骤:
- 这个类有两种 setter 方法。第一个,set 任意转换对象,并且在该类的不可变版本中没有位置。invert 可以通过使其创建新对象而不是修改现有对象来适应第二个。
- 所有字段都已经 private; 他们进一步合格 final。
- 该类本身被声明 final。
- 只有一个字段是指一个对象,该对象本身是不可变的。因此,没有必要改变“包含”可变物体的状态的保障措施。
public final class ImmutableRGB {
// 值必须是 0 到 255.
final private int red;
final private int green;
final private int blue;
final private String name;
private void check(int red,
int green,
int blue) {
if (red < 0 || red > 255
|| green < 0 || green > 255
|| blue < 0 || blue > 255) {
throw new IllegalArgumentException();
}
}
public ImmutableRGB(int red,
int green,
int blue,
String name) {
check(red, green, blue);
this.red = red;
this.green = green;
this.blue = blue;
this.name = name;
}
// 这个rgb的算法没有什么意义吧?
public synchronized int getRGB() {
return ((red << 16) | (green << 8) | blue);
}
public synchronized String getName() {
return name;
}
/**
* 反转颜色
*/
public ImmutableRGB invert() {
return new ImmutableRGB(255 - red, 255 - green, 255 - blue, "Inverse of " + name);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44