Всем привет!
Есть singleton, но с двухстадийным созданием. Типа такого:
class TwoPhaseSingleton
{
static s_instance = new TwoPhaseSingleton();
public static Instance { get { return s_instance; } }
private TwoPhaseSingleton()
{
}
public void Init() { ... }
}
// где-то на старте приложения...
TwoPhaseSingleton.Instance.Init();
Временами вторая фаза падает. В результате остается неинициализированный объект, вызывающий кучу ошибок в дальнейшем до ручного рестарта приложения.
Вторая фаза создания объекта может быть повторена через некоторое время и может пройти успешно.
Можно было бы отловить на старте приложения ошибку и повторить инициализацию через какой-нить sleep, но лень. Поэтому пошел ленивым путем, то есть при каждом обращении к экземпляру объекта проверять, что он инициализирован, и если нет, то выполнять инициализацию. Что-то типа такого:
...
public static Instance
{
get
{
if(!s_instance.Initialized)
{
s_instance.Init();
}
return s_instance;
}
}
...
Но диспетчеризацию по if'ам не люблю. Мне более симпатичен такой вариант:
class TwoPhaseSingleton
{
static s_instance = new TwoPhaseSingleton();
public static Instance
{
get
{
s_instance.Init();
return s_instance;
}
}
private TwoPhaseSingleton()
{
Init = InitReal;
}
public Action Init { get; private set; }
private void InitReal() { ...; Init = InitFake; }
private void InitFake() { }
}
То есть Init — это не метод, а делегат. До инициализации в Init лежит функция, которая действительно выполняет инициализацию. После успешной инициализации в Init заносится пустая функция, которая ничего не делает.
Поругайте, сравните оба эти варианта. Какие есть плюсы и минусы?
Первый вариант очевиднее и понятнее для ООП. Второй ближе к ФП.
В первом варианте меньше расход памяти.
А что со скоростью выполнения?