【发布时间】:2016-03-05 22:10:32
【问题描述】:
我一直在阅读空对象模式将帮助您避免空检查和空指针异常,从而使您的代码更清晰易懂。
我从未使用过它,我觉得它很有趣。 “null”不会占用内存,但如果我开始用创建“默认”对象来替换我的 null 检查,从长远来看,这个过程会对内存产生负面影响吗?
例如:
空对象模式
public void DoSomething()
{
User user = this.GetUser(id);
string strDisplayName = user.DisplayName;
}
public User GetUser(int id)
{
User user = this.LoadUserFromDB(id);
if(user == null)
return User.CreateNull();
return user;
}
所以,我一走出方法的作用域,后面的对象就会被GC回收。 但是如果我在离开作用域之前通过一个循环呢?
public void DoSomething()
{
users = this.GetAllUsers();
foreach(User user in users)
{
string strAddress = user.Address.StreetName;
//continue tasks
}
}
同时在其他班级
public Class User
{
public Address Address
{
get
{
if(this.Address == null)
this.Address = Address.CreateNull();
return this.Address;
}
}
}
public class Address
{
private string streetName;
public virtual string StreetName
{
get { return this.streetName; }
set { this.streetName = value; }
}
public static CreateNull()
{
return new NullAddress();
}
}
public class NullAddress : Address
{
public override string StreetName
{
get { retun String.Empty; }
}
}
空检查
User user = this.GetUser(id);
string strDisplayName = String.Empty;
if(user != null)
{
strDisplayName = user.DisplayName;
}
只需检查用户是否不为空,因此分配属性值。我不会创建“空”对象
提前致谢。
【问题讨论】:
-
也许只是偏好,但如果是数据库实体,我会考虑使用
Optional<User>而不是“假”用户,因为Optional保留了“未找到用户”的含义。真正的空对象只有在不会导致正确对象和空替换之间混淆的情况下才能很好地工作(参见Liskov substitution principle)。就像空的Lists 而不是null。或者像记录器这样只使用输入的实现。 -
在 Jon 说应该共享对象的内存问题之外,我不确定编写上游代码以避免破坏下游代码是您想要的方式。正确编写/测试的代码将暴露问题,然后您可以解决根本问题。就个人而言,除非
User和Address是Structs(模式说使用User.Empty之类的东西),否则我会让错误传播并通过编写良好的单元测试来暴露它们。
标签: java c# design-patterns null