Предположим, у меня есть класс, который предоставляет некоторые данные для моего приложения. Первоначально данные поступают из базы данных, и я предоставляю их с помощью некоторых методов, которые обрабатывают всю базу данных и представляют результат в виде пригодного для использования класса вместо необработанного результата запроса. Этот класс должен выполнить некоторую настройку (не сложную), чтобы убедиться, что любой вызванный метод может использовать базу данных (например, подключиться к базе данных, убедиться, что она содержит некоторую критическую информацию, например, c). Итак, если бы я поместил его в метод (скажем, метод Init (), который бы обрабатывал проверку базы данных, подключение к ней, проверку того, что она содержит информацию), я должен был бы убедиться, что этот метод вызывается раньше любой другой метод. Итак, я обычно нахожу, что вместо того, чтобы делать это:
public class DataProvider
{
private SqlController controller;
public void Init()
{
controller = new SqlController();
controller.Init();
controller.ConnectToDataBase();
CheckForCriticalInfoInDatabase();
}
public Data GetData()
{
// get data from database (not actually going to use raw queries like that, just an example)
var queryResult = sqlController.RunQuery("SELECT something FROM SOME_TABLE");
// and present it as usable class
Data usefulData = QueryResultToUsefulData(queryResult);
return usefulData;
}
...
}
, а затем всегда проверять, чтобы я вызывал Init () перед GetData (), я делаю что-то вроде
private SqlController _controller;
private SqlController controller
{
get
{
if (_controller == null)
{
_controller = new SqlController();
_controller.Init();
_controller.ConnectToDataBase();
CheckForCriticalInfoInDatabase();
}
return controller;
}
}
Итак, Теперь я могу быть уверен, что не буду использовать неинициализированный SqlController, и мне не нужно делать ту же самую проверку на ноль в каждом методе, который его использует. Тем не менее, я никогда не замечал, чтобы получатели использовались таким образом в коде других людей.
Есть ли какая-то ловушка, которую я не вижу? Для меня это выглядит так же, как ленивая инициализация, за исключением того, что я использую ее не потому, что инициализация тяжелая или длинная, а потому, что я не хочу проверять порядок, в котором я вызываю методы. Этот вопрос указывает на то, что он не является поточно-ориентированным (в моем случае это не проблема, плюс я предполагаю, что он может быть поточно-ориентированным при некоторых блокировках), и что установка свойства в null приведет к неинтуитивному поведению (Не беспокойся, потому что у меня вообще нет сеттера и поле поддержки не должно быть затронуто в любом случае).
Кроме того, если этот вид кода является практическим, то как правильно чтобы мои методы не зависели от порядка их вызова?