EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.

 

不要返回null之EmptyFactory

有很多书上都提出过一个建议:不要返回null对象。

比如下面的GetUsers方法:

public class User

{

    public string Id { get; set; }

    public string Name { get; set; }

}

 

public List<User> GetUsers()

{

    List<User> result = new List<User>();

 

    // search db for user

    return result;

}

如果其他方法由GetUsersOfxxxGetUsersByXXX之类的方法,那么就有大量

List<User> result = new List<User>();

 

考虑到这一点,可以将new List<User>()  封装到方法中,这就是工厂模式了.

因为可能不是List<User> ,也许是Stack<User> 更或者是ObservableCollection<User>

 

所以配合泛型,代码如下:

public static class EmptyFactory

{

    public static T Empty<T>() where T : IEnumerable, new()

    {

        return new T();

    }

}

 

使用如下:

List<string> emptyList = new List<string>();

Stack<string> emptyStack = new Stack<string>();

ObservableCollection<string> emptyObserable = new ObservableCollection<string>();

 

emptyList = EmptyFactory.Empty<List<string>>();

emptyStack = EmptyFactory.Empty<Stack<string>>();

emptyObserable = EmptyFactory.Empty<ObservableCollection<string>>();

虽然这样写可以满足要求,但是可以发现基本没什么好处,写EmptyFactory还不如new 来得快。

不过如果能够缓存对象的话,也许EmptyFactory有作用。

考虑到这一点,为EmptyFactory增加缓存机制的代码如下,使用Dictionary<Type,Object> 来实现

public static class EmptyFactory
{
    private static Dictionary<Type, object> cacheEmptyObjects = 
                     new Dictionary<Type, object>();
    public static T Empty<T>() where T : IEnumerable, new()
    {
        Type genericType = typeof(T);
        if (cacheEmptyObjects.ContainsKey(genericType))
        {
            return (T)cacheEmptyObjects[genericType];
        }
        else
        {
            T tempEmptyObject = new T();
            cacheEmptyObjects.Add(genericType, tempEmptyObject);
            return tempEmptyObject;
        }
    }
}

 

测试代码如下:

 image

 

不过这种方法有一个缺陷,对于值类型而言,需要装箱

其根本原因是因为EmptyFactory不知道T是什么,如果EmptyFactory知道T的话,那么就可以使用Dictionary<T,T> 的缓存了。

解决这个问题的思路是将EmptyFactory变成泛型类

代码如下:

public static class EmptyFactory<T> where T : IEnumerable, new()
{
    private static Dictionary<Type, T> cacheEmptyObjects = new Dictionary<Type, T>();
    public static T Empty()
    {
        Type genericType = typeof(T);
        if (cacheEmptyObjects.ContainsKey(genericType))
        {
            return cacheEmptyObjects[genericType];
        }
        else
        {
            T tempEmptyObject = new T();
            cacheEmptyObjects.Add(genericType, tempEmptyObject);
            return tempEmptyObject;
        }
    }
}

 

使用的时候,只需要

image

当然也可以EmptyFactory<List<User>>.Empty();

 

为什么不用Enumersble.Empty<T>方法呢?

因为Enumerable.Empty<T> 返回的是IEnumerable<T>对象。

posted @ 2011-09-27 22:52  LoveJenny  阅读(2280)  评论(19编辑  收藏  举报
EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.