程式碼到處是處理null欄位或變數的重複邏輯.
假設有個JobRunner
類別, 用來執行特定任務的開始與結束.
而範例只有一個任務CopyJob
類別.
以下的CopyJob
的實作都是dummy並無真實流程:
internal class CopyJob
{
public bool Start()
{
return true;
}
public bool AnySetting()
{
return true;
}
public bool Stop()
{
return true;
}
}
public class JobRunner
{
private CopyJob _copyJob = null;
public bool Start()
{
if (_copyJob != null)
{
return _copyJob.Start();
}
return false;
}
public bool Stop()
{
if (_copyJob != null)
{
return _copyJob.Stop();
}
return false;
}
public bool AnySetting()
{
if (_copyJob != null)
{
return _copyJob.AnySetting();
}
return false;
}
public void Initialize()
{
_copyJob = new CopyJob();
}
}
JobRunner
的Start
, Stop
與AnySetting
都得先檢查_copyJob
是不是null.
既然是null與非null都有各自的流程, 因此我們建立另一個新類別NullCopyJob
, 繼承自CopyJob
, 如下重構:
internal class CopyJob
{
public virtual bool Start()
{
return true;
}
public virtual bool AnySetting()
{
return true;
}
public virtual bool Stop()
{
return true;
}
}
internal class NullCopyJob : CopyJob
{
public override bool Start()
{
return false;
}
public override bool Stop()
{
return false;
}
public override bool AnySetting()
{
return false;
}
}
public class JobRunner
{
private CopyJob _copyJob = new NullCopyJob();
public bool Start()
{
return _copyJob.Start();
}
public bool Stop()
{
return _copyJob.Stop();
}
public bool AnySetting()
{
return _copyJob.AnySetting();
}
public void Initialize()
{
_copyJob = new CopyJob();
}
}
經過此重構, JobRunner
都是統一呼叫CodeJob
的方法, 不必再判斷null.
以上範例是以class繼承的null object, 但未來子類別可能忘記要override.
則可以改用interface.