Задать вопрос
@stupid_Dotnetchik

Правильна ли реализация наследования синглтона?

Ку!
Небольшое десктоп приложение, есть пара десятков классов, плодить объекты которых не хочется.
Первое решение приходящее на ум - сделать их статическими, со всеми вытекающими последствиями: все поля классов статические, все методы тоже статические, что кажется не сильно правильным в ООП-языке.
Вторая идея - сделать всё синглтонами:
public class YellowClass
	{
		private static YellowClass _instance;
		private YellowClass() { }
		public static YellowClass GetInstance()
		{
			return _instance ?? (_instance = new YellowClass());
		}
	}

Однако копипастить в каждый класс 6 строк кода (в примерах посложнее тредсэйфом и поболее) кажется весьма унылым.
Нашёл несколько примеров 'наследуемых синглтонов', подумал что счастье близко. Один из них: пр
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace DemoApplication
{
	static class Program
	{
		static void Main(string[] args)
		{
			var yellowClass1 = new YellowClass();
			var yellowClass2 = YellowClass.Instance;

			Debug.Print(yellowClass1.Equals(yellowClass2) ? "All good!" : "WTF???");
		}
	}

	public class Singleton<T>
	{
		[SuppressMessage("ReSharper", "InconsistentNaming")]
		private static readonly Lazy<T> _instance = new Lazy<T>(CreateInstance);

		private static T CreateInstance()
		{
			return (T)Activator.CreateInstance(typeof(T), true);
		}

		public static T Instance
		{
			get { return _instance.Value; }
		}
	}

	public class YellowClass : Singleton<YellowClass>
	{
	}
}

Мне казалось, что синглтон подразумевает существование только 1 экземпляра класса в виртуальной машине, а тут я конструктором создаю ещё 1 экземпляр. Можно конечно для всех классов-наследников добавить приватные конструкторы, но я (или коллега) просто можем забыть это сделать через полгода при добавлении ещё пары классов этой категории, что может привести к коварным багам (уже были случаи).

Я нагуглил плохие примеры наследования синглтона? Может можно как-нибудь обойтись без приватного конструктора в каждом классе-наследнике?
  • Вопрос задан
  • 464 просмотра
Подписаться 2 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 4
zagayevskiy
@zagayevskiy
Android developer at Yandex
По-моему, фигня и бред. Открой для себя dependency injection.
Ответ написан
Комментировать
Griboks
@Griboks Куратор тега C#
Ну и, чтобы не накладывать дополнительных ограничений на T (в данном случае - наличие непараметризованного конструктора), можно написать так: (T)Activator.CreateInstance(typeof(T), true);

Так может быть стоило прочитать сначала описание этого примера?
Ответ написан
Комментировать
@kttotto
пофиг на чем писать
Я пользуюсь такой конструкцией, проверенной временем
public class Singleton<T> where T : class
{
	private static readonly Lazy<T> _instance = new Lazy<T>(() => (T)typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[0], null).Invoke(null), true);

	public static T Instance => _instance.Value;
}

public sealed class CustomSingleton : Singleton<CustomSingleton>
{
}

var single = CustomSingleton.Instance
Ответ написан
Комментировать
Первое решение приходящее на ум - сделать их статическими, со всеми вытекающими последствиями: все поля классов статические, все методы тоже статические, что кажется не сильно правильным в ООП-языке.

Если хотите писать процедурно - пишите процедурно) То, что вы сделаете все синглтонами - не сделает ваш код ООП-шным. Он будет только притворяться ООПшным, но не быть им. Но, возможно, оно вам и не нужно?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы