Swift singleton против статических свойств / методов - PullRequest
0 голосов
/ 25 января 2019

Согласно этому сообщению в блоге и ответу, получившему наибольшее количество голосов на этот вопрос переполнения стека , который в свою очередь цитирует документацию Apple лучший способ создать синглтон в современном Swift:

class Singleton  {
   static let sharedInstance = Singleton()
}

Хотя это и не упоминалось, вероятно, также требуется private init().

Для меняболее простой альтернативой будет преобразование всех свойств и методов в static и удаление свойства sharedInstance.

Например, предположим, что я написал класс со свойством и методом, следуя приведенным выше советам, какследует:

class Singleton {
  static let sharedInstance = Singleton("whatever")

  var myProperty: String

  func myMethod() {
    // ...
  }

  private init(_ myProperty) {
    self.myProperty = myProperty
  }
}

Если пользователю необходимо получить доступ к рассматриваемому свойству, он напишет Singleton.sharedInstance.myProperty, а если ему нужно вызвать метод, он напишет Singleton.sharedInstance.myMethod().

Я предлагаю переписать класс следующим образом:

class Singleton {
  static var myProperty: String = "whatever"

  static func myMethod() {
    // ...
  }
}

Итак: меньше шаблонного кода и меньше символов для ввода при доступе к свойству (просто Singleton.myProperty) и методу (Singleton.myMethod()).

Одним из недостатков является то, что доступ к правильномуТип и метод внутри класса должны быть полностью прописаны (Singleton.myProperty и Singleton.myMethod()), по сравнению с myProperty и myMethod() для предыдущего решения.

Таким образом, это немногонемного проще для пользователя (отбрасывание части sharedInstance) и немного сложнее для автора классов (который должен добавить Singleton. перед всеми обращениями).Кажется разумным, что, когда перед выбором дизайна, который либо одобряет пользователя или автора класса, лучшим вариантом является предпочтение пользователя.

Никто другой, кажется, не поддерживает метод, который я предложил для создания одиночного,поэтому я чувствую, что с этим что-то не так.Будет ли кто-то так любезно указать, что это такое?

1 Ответ

0 голосов
/ 25 января 2019

Для меня более простой альтернативой было бы преобразование всех свойств и методов в статические и удаление свойства sharedInstance.

Они не делают то же самое. Рекомендуемый подход на самом деле не является единичным. Это просто известный пример. Концепция шаблона Singleton заключается в том, что должен быть только одним экземпляром. Сочетание шаблона общего экземпляра состоит в том, что может быть более одного экземпляра, но есть тот, который вам, вероятно, нужен, и вам нужен легкий доступ к нему.

Преимущество общих экземпляров в том, что они не магические. Они просто экземпляры. Это означает, что они могут быть переданы как ценности. Их можно заменить другими экземплярами, которые могут быть настроены по-другому. Их легче тестировать (потому что их можно передавать в функции).

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

Если вы посмотрите вокруг Какао, то обнаружите, что общие экземпляры чрезвычайно распространены для вещей, которые могут быть синглетонами в других средах, и это было очень мощно. Например, есть хорошо известный NotificationCenter, называемый default, и это, вероятно, единственный, который вы когда-либо использовали. Но вполне допустимо создать приватный NotificationCenter, который независим (я фактически сделал это в рабочем коде).

Тот факт, что UIDevice.current - это то, как вы получаете доступ к устройству, а не к статическим методам, оставляет возможность новых API, которые могут обрабатывать несколько устройств (это также помогает при модульном тестировании). В самых ранних версиях iOS единственным UIScreen был .main, и, возможно, имело смысл сделать его одиночным. Но поскольку Apple этого не сделала, при добавлении зеркалирования в 4.3 было легко говорить о втором экране (UIScreen.mirrored). Как правило, вы должны очень медленно предполагать, что может быть только одно из чего-либо.

...