No, non è un buon candidato.
-
Che cosa succede se acquisti un secondo termometro per ottenere la temperatura in due posizioni diverse?
-
Che cosa succede se si desidera creare un finto o uno stub del termometro per unire le parti di test che si basano su di esso?
Con singleton, finirai per fare qualcosa del tipo:
public class TemperatureRealTimeDisplay
{
// Show the current temperature to the user.
public void Show()
{
var temperature = Thermometer.Instance.Measure();
...
}
}
public class TemperatureChart
{
// Record the temperature in order to display a chart over time.
public void OnTimer()
{
var temperature = Thermometer.Instance.Measure();
...
}
}
...
var display = new TemperatureRealTimeDisplay();
var chart = new TemperatureChart();
Questo codice:
-
Non può essere testato, poiché si basa sul termometro che non può essere sostituito da un mock o da uno stub,
-
È difficile da mantenere o riutilizzare data la sua dipendenza dal termometro attuale.
Se, d'altra parte, si utilizzano le istanze e Iniezione di dipendenza:
public interface IProbe<TResult>
{
public TResult Measure();
}
public class HardwareThermometer : IProbe<Temperature>
{
...
}
public class RealTimeDisplay<TMetric>
{
public RealTimeDisplay<TMetric>(IProbe<TMetric> probe)
{
this.probe = probe;
}
public void Show()
{
var current = this.probe.Measure();
...
}
}
public class Chart<TMetric>
{
public Chart<TMetric>(IProbe<TMetric> probe)
{
this.probe = probe;
}
public void OnTimer()
{
var current = this.probe.Measure();
...
}
}
...
var thermometer = new HardwareThermometer();
var temperatureDisplay = new RealTimeDisplay(thermometer);
var temperatureChart = new Chart(thermometer);
rimuovi le dipendenze, rendendo possibile utilizzare le classi generali RealTimeDisplay
e Chart
che possono essere riutilizzate per qualsiasi altra cosa, come la misurazione del carico della CPU o il numero di WTF al secondo durante una revisione del codice . Con:
public class ProbeStub : IProbe<int>
{
...
}
possono essere facilmente testati.
Non puoi usare sia dependency injection che singleton? È possibile, ma il punto di utilizzo di un singleton consiste nell'essere in grado di utilizzare l'istanza ovunque senza doverla passare attraverso i parametri lungo la catena. Nel mio esempio, crei solo un'istanza di thermometer
una sola volta, rendendo inutile un singleton.
Il fatto che il singleton garantisca che solo una istanza verrà mai creata non è particolarmente utile nel mio esempio. RealTimeDisplay
e Chart
ricevono già un'istanza di un termometro, quindi l'incentivo a creare un altro termometro è basso. L'unico rischio rimanente è di finire con un codice come questo nel punto di accesso dell'applicazione:
var temperatureDisplay = new RealTimeDisplay(new HardwareThermometer());
var temperatureChart = new Chart(new HardwareThermometer());
ma è improbabile che un manutentore esegua tali modifiche.