Pull to refresh

Comments 31

Singleton (в народе называемый паттерном программирования)
Не программирования, а проектирования. И не в народе, а в первоисточнике. А в народе синглтон чаще называют антипаттерном. Но это другая история…
Опечатался про проектирование. Исправил.
Да, думаю следует сказать, что использование синглтона сплошь и рядом зло.
А зла не хватает.Сильно и регулярно.
Вот на самом деле смешная ситуация с программистами. Работали у меня несколько человек, дак банально даже синглтон не могли использовать, но при этом считали себя высококвалифицированными специалистами — лезли в Yii и в Laravel, но лезли видимо в слепую без представления. Понятное дело что такие люди проработали не долго, но суть в том, что таких кадров встречается много. Даже в плане кода смотришь порой продукты крупных компаний, а там не то что синглтоном не пахнет, там даже ООП как такового принципы не используются.
Синглтон — средство, как например средство от тараканов. Не стоит добавлять его в каждое блюдо, но для против тараканов он эффективнее тапка.Мораль — нет плохих средств, но есть плохие программисты. Главное, чтоб код был симпатичный и понятный.
// Метод, выполняемый при старте игры
    void Start () {
        // Теперь, проверяем существование экземпляра
	if (instance == null) { // Экземпляр менеджера был найден
	    instance = this; // Задаем ссылку на экземпляр объекта
	} else if(instance == this){ // Экземпляр объекта уже существует на сцене
	    Destroy(gameObject); // Удаляем объект
	}

        // Теперь нам нужно указать, чтобы объект не уничтожался
        // при переходе на другую сцену игры
	DontDestroyOnLoad(gameObject);

	// И запускаем собственно инициализатор
	InitializeManager();
    }

Что будет когда instance != null?
Будет instance = this;
Тут идет два варианта: либо instance=null, либо instance=this.

Эта часть кода проверяет на дубликаты при переходе на другую сцену.
По-моему, ваше уловие else if(instance == this) не выполнится никогда, так как, если instance не null, то и не this точно, так как метод Start класса MonoBehaviour, движок вызывает только один раз при инициализации компонента.
Мой косяк. Нужно было сделать немного по другому.
if(instance!=null) Destroy(gameObject);
instance = this;
Даже забьём на то, что по идее нужно разрушать компонент, а в этом случае уничтожается геймобжект. Последний зашёл, значит ты и прав? Реиницилизация в каждой сцене где присутствует? Зачем?

Я вообще против синглтонов монобехов. Но если уж юзать, то есть вот такая реализация (в самом низу), она даже лочит где надо. wiki.unity3d.com/index.php/Singleton

Но в целом синглтоны монобехи не нужны в большинстве случаев. Да и не удобны в целом.
Правда у меня к этой реализации дженериком, есть ещё проверка от дурака, чтобы нельзя было навесить компонентой и т.п.
Стоит отметить, что движок называется Unity. А unity3d — это домен, на котором хостится сайт.
Я понимаю что он называется Unity. Во многих ресурсах раньше он фигурировал как Unity3D, так что осталась привычка. Даже где-то очень давно на официальном сайте видел Unity3D название фигурировало, но потом стало просто Unity.
Синглетон не добро и не зло. Есть кейсы в которые он приносит удобства, есть наоборот, проблемы. Один из примеров — объект настроек(settings) вашего приложения(игры), к которому вы имеете доступ отовсюду, без лишних телодвижений.
Соглашусь, в вебе мне достаточно симпатизирует синглтон в качестве основы для веб-сайтов. Тот же CodeIgniter мне безумно нравится. Однако в Unity использование Singletone сплошь и рядом не есть хорошо из-за большого количества связываний. Как по мне в рамках разработки игры он больше подходит для чего-то глобального.
Те кто пишут что синглтон зло, просто не умеют его использовать. Начитаются всяких статей про антипаттерны и везде вставят свое «не используйте синглтон». Именно в Unity этот паттерн полезен.
Тут скорее зависит от того, как его использовать. Если использовать без знания и понимания зачем это все нужно — то любой паттерн будет бесполезен. Сам по себе Unity впринципе имеет удобную архитектуру на основе компонентов — для простых проектов и этого хватит с лихвой.
Вот, «компоненты» ключевое слово, помнится кто-то даже говорил, что в Unity не ООП, а КОП — компонентно-ориентированное программирование. Попытки применять чистое ООП и различные паттерны в создании игр на Unity может привести к головной боли. Я для себя принял правило не пытаться раздувать архитектуру и максимально использовать готовые решения, а так же активно пользоваться документацией и туториалами на офсайте, очень много там хитростей полезных разобрано.
В Unity он просто менее опасен, так как там нечасто кто-то работает в много потоков. У самого паттерна есть очевидные плюсы и минусы. Основной при неправильном использовании — это нереальная связность системы. В случае многопоточности с синглтонами очень неудобно работать. Если забыть про дедлоки и сделать нормальные блокировки и т.п., то всё равно сложно отследить порядок морфирования при дебаге. Сингтлон просто позволяет меньше думать над тем, как архитектурно красиво прокинуть некоторые сервисы, которые скорее всего будут в единичном экземпляре. Я использую синглтоны часто, но это не отменяет огромного количества недостатков. Просто, на мой взгляд, основное преимущество — это скорость разработки. За которую правда придётся платить в будущем.
Вот пример реализации синглтона в юнити, без использования объекта на сцене, соответственно, при переходе между сценами не надо следить за тем чтобы объект не был уничтожен. Класс бутстрапер тоже не нужен, так как синглтон сам создает свой экземпляр при первом к нему обращении.
public class SomeSingleton : ScriptableObject
{
  private static SomeSingleton _instance;
  
  public SomeSingleton ()
    {
        if (_instance != null)
        {
               return;
        }
        _instance = this;
    }
  
    public static SomeSingleton Instance
    {
        get
        {
            if (_instance == null)
            {
                ScriptableObject.CreateInstance<SomeSingleton>();
            }
            return _instance;
        }
    }
}
Интересный пример, тоже имеет место быть. Но мне лично удобней использовать Bootstraper-ы для контроля + у меня не на всех сценах нужно проводить обращение к Singleton, но сам по себе он должен выполнить задачу при инициализации (например загрузить настройки языка).
Не имеет места быть ни ваш, ни пример из статьи. Это просто не синглтоны. Так как с таким описанием класса я могу спокойно создать много инстанстов. А реализация выше творить будет вообще полный треш с точки зрения мусора. У синглтона должен быть приватный конструктор, как минимум. В случае монобеха, там всё вообще сложнее. А описанные реализации — это очень опасные и даже вредные конструкции.
Ваш пример реализации в студию!
Вообще ссылку я скинул выше. Я терпеть не могу монобеховские синглтоны, так как они требуют слишком много обвязки вокруг. Но скажем если взять пример клиента из моей статьи про Unet то, вот не монобеховский синглтон
github.com/Nox7atra/Simple-Unity-Client-Server/blob/master/Assets/Scripts/Networking/Client.cs
В случае с монобеховским в том же репозитории есть не совсем синглтон, но шаблонный (я просто немного упростил пример выше, так как многопоточностью в коде и не пахло, а пример выше учитывает и её) Он находится в каталоге Utils
А зачем инициализировать объект, если у нас уже есть инстанс? Ну то есть при вызове Destroy, мы дальше пойдём инициализировать объект. Это баг или фича?
Вызов InitializeManager(); не обработается после Destroy, т.к. объекта уже не будет. Так же как в PHP после Exit код не будет обрабатываться

Кроме того, что синглтоном называют некий аггрегирующий класс, ничего не понял. Дочитал до слова "responce" и кажется понял — почему.

Singleton это не агрегирующий класс, это класс экземпляр которого может быть только один. Ну и средство быстрого глобального доступа к этому экземпляру (public static field или property).
Sign up to leave a comment.

Articles