任何使Null对象不可变的标准模式或策略

时间:2012-12-03 10:24:20

标签: java design-patterns

在java中,我们更喜欢null object模式,而不是在所有引用中使用非null检查来混淆代码。最近,我们遇到了一个问题,即通过保留null object对象来使用singleton
假设我们有Person类,如下所示

public class Person {
 public String firstName;
 public String lastName;
 public boolean isNull() {
  return false;
 }
 public static final Person NULL = new Person() {
  public boolean isNull() { return true; }  
 }
}

在这种情况下,虽然我已将NULL对象声明为final,但我仍然可以修改成员变量及其全局可用。

Person nullRef = Person.NULL;
Person.NULL.firstName = "sample";
System.out.println(nullRef.firstName);

在这种情况下,它只有三个字段,我可以通过覆盖这三个getter方法来解决可变性问题。但实际上会有很多字段难以覆盖所有相应的getter方法。
是否有任何标准模式或策略来解决NULL对象中的可变性问题?

3 个答案:

答案 0 :(得分:2)

使用Google Guava库中的Optional

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

引用图书馆文档:

  

除了提供null a的可读性增加之外   名称,Optional的最大优点是它的白痴证明

这是处理空对象的更自然的方式

Optional Google Guava

答案 1 :(得分:1)

你需要有两个级别的接口:一个用于不可变部分(只有getter和immutable方法),另一个用于扩展不可变接口的可变部分。然后需要对代码进行重构,以便仅在所有相关位置使用最严格的接口。

所以

public interface ImmutablePerson {
  final String getFirstName();
}

public interface MutablePerson extends ImmutablePerson {
  final void setLastName(final String newName);
}

是的,现在MutablePerson“是一个”ImmutablePerson,但只在用作一个时:)

此外,isNull检查表明您需要更多地考虑控制反转。

具体:

当你发现自己编写像

这样的代码时
if (!person.isNull()) {
  person.setLastName("Foo");
}

你应该只使用你的Null对象并将其视为一个中性元素。像这样:

首先:

final Person NullPerson = new Person() {
  void setLastName(final String newName) {
    // Do nothing, this is a neutral (Null) object
  }
}

......然后是:

// Never need to check for isNull ever again - null objects just decide to ignore your request
person.setLastName("Foo");

答案 2 :(得分:0)

  • 您需要将所有字段设为“私有”,以便除了getter代码之外无法访问这些字段。
  • 您需要修改“setter”方法而不是getter方法,以使其不可变。 例如。

    public String setFirstName(String name){ 如果(!ISNULL()){ firstName = name; } }