在组合对象中使用Null作为标志是一件好事吗?

时间:2014-01-07 16:24:05

标签: c# .net oop

我的申请中有一个情况。我收到了服务的回复。我有时需要在数据库或其他媒体中的缓存中转换和保存响应。可能还有一个场景,我不需要保持响应,但只需要转换respone并返回对象。我已经实现了以下设计:

public class Response { }

class MyData { }

interface IPersistance 
{
    public void PersistData(MyData data);
}

public class DBPersitance : IPersistance 
{
    public void PersistData(MyData data) { }
}

public class CachePersitance : IPersistance
{
    public void PersistData(MyData data) { }
}

public class MySeviceData
{
    private IPersistance persistence;

    public MySeviceData(IPersistance persistance)
    {
        _persistance = persistance;
    }

    public MyData GetServiceData(Response reponseXML)
    {
        MyData output = new MyData();

        // Here output object is filled with data from responseXML

        // Object persistance as defined in constructor
        if(_persistance!=null)
            _persistance.PersistData(output);

        return output;
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyData output = new MyData();
        Response responseXML = new Response() ;

        //Case 1: Cache the response
        CachePersitance cache = new CachePersitance();
        MySeviceData srvData = new MySeviceData(cache);
        output = srvData.GetServiceData(responseXML);

        //Case 2: Write the response in Database
        DBPersitance db = new DBPersitance();
        MySeviceData srvData = new MySeviceData(db);
        output = srvData.GetServiceData(responseXML);

        //Case 3: No need to persist. Only Convert and return the response
        MySeviceData srvData = new MySeviceData(null);
        output = srvData.GetServiceData(responseXML);
    }
}

在上面的实现中,在我只需要转换对象(没有persiatance)的场景中,我已经通过null persistance对象。这种方法是否正确?有人可以为这种要求提出更好的设计吗?

1 个答案:

答案 0 :(得分:1)

一种思维方式是尽可能避免if检查null。我们可能同意与否(这将是非常基于意见的,IMO很好,但暨grano salis null携带信息时并不总是邪恶的)

使用空类而不是null会在读取代码时明显表达意图( Persistance为null?这意味着什么?默认一个或没有一个?如果默认一个那么这是什么默认值? )。

空的IPersistance(称为例如NoPersistance)实现可行。如果这是最常见的情况,您甚至可以提供没有参数的构造函数重载(如下例所示)(并且您不需要将其显式化,在这种情况下只需删除它)。

public class NoPersitance : IPersistance {
    public void PersistData(MyData data) {
        // Nothing to do
    }
}

public class MySeviceData {
    private IPersistance _persistance;

    public MySeviceData(IPersistance persistance) {
        if (persistance == null)
            throw new ArgumentNullException("persistance");

        _persistance = persistance;
    }

    public MySeviceData() : this(new NoPersistance()) {
    }

    public MyData GetServiceData(Response reponseXML) {
        Debug.Assert(_persistance != null);

        MyData output = new MyData();
        // Fill your object's data

        // Store object somewhere
        _persistance.PersistData(output);

        return output;
    }
}

像这样使用(没有参数意味着没有持久性,可以在MyServiceData构造函数重载中记录):

MySeviceData srvData = new MySeviceData();
output = srvData.GetServiceData(responseXML);

或者像这样:

MySeviceData srvData = new MySeviceData(new NoPersistance());
output = srvData.GetServiceData(responseXML);