Любая причина, по которой не используется, использует одиночную "переменную" в Swift?

В сентябре 2015 года, как именно вы делаете синглтон в Swift:

public class Model
    {
    static let shared = Model()
    // ( for ocd friends ... private init() {} )

    func test()->Double
        {
        return 3.33
        }
    }

затем в другом месте...

// file ViewController.swift, say
import UIKit
class ViewController:UIViewController
    {
    override func viewDidLoad()
        {
        super.viewDidLoad()
        print("view controller loaded!")
        print("singleton test! \( Model.shared.test() )")
        }
    }

Нет проблем.

Однако. Я добавляю эту маленькую вещь...

public let model = Model.shared
public class Model
    {
    static let shared = Model()

    func test()->Double
        {
        return 3.33
        }
    }

тогда вы можете просто выполнить следующие действия по всему проекту:

class ViewController:UIViewController
    {
    override func viewDidLoad()
        {
        super.viewDidLoad()
        print("view controller loaded!")
        print("singleton test! \( model.test() )")
        }
    }

Традиционная идиома:

Model.shared.blah()... вы видите это везде в базе кода

"моя" идиома:

model.blah()... вы видите это везде в базе кода

Итак, это приводит к тому, что все выглядит красиво:

введите описание изображения здесь

(В вашем проекте эти "одиночные переменные" будут такими, как scores., networking., heuristics. или что бы ни случилось в вашем проекте.)

Таким образом, это "макроподобная" идиома.

Единственная цель - внешний вид кода.

Упрощение появления ImportantSystem.SharedImportantSystem до importantSystem. во всем проекте.

Может ли кто-нибудь увидеть какие-либо проблемы с этой идиомой?

Проблемы могут быть техническими, стилистическими или любой другой категорией, если они действительно глубоки.

Ответы

Ответ 1

Функционально они очень похожи, но я бы посоветовал использовать синтаксис Model.shared, потому что это делает абсолютно ясным, где бы вы его ни использовали, что вы имеете дело с синглом, тогда как если у вас есть только это model глобальное плавание там, неясно, с чем вы имеете дело.

Кроме того, с помощью глобальных переменных (esp с простым именем типа "модель" ) вы рискуете иметь некоторый будущий класс, который имеет аналогичные имена, и случайно ссылается на неверный.

Для обсуждения общих соображений относительно глобальных переменных v синглетонов v других моделей см. Глобальные переменные являются плохими, которые, несмотря на довольно ведущий заголовок, представляет собой трезвую дискуссию, имеет несколько интересных ссылок и представляет альтернативы.


Кстати, для ваших "друзей OCD" (в пределах которых, я думаю, я должен считать себя, потому что я думаю, что это лучшая практика), не только объявит init private, но вы, вероятно, объявите весь класс должен быть final, чтобы избежать подкласса (в этот момент он становится двусмысленным для ссылок shared).

Ответ 2

Есть несколько вещей, которые нужно учитывать при использовании этого подхода:

Глобальная переменная

Глобальная переменная сама по себе не имеет большого значения, но если у вас есть довольно некоторые глобальные переменные, у вас могут возникнуть проблемы с автозавершением, поскольку она всегда будет предлагать эти глобальные переменные.

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

Использование глобальных переменных обычно считается плохой практикой.

Шаблон singleton

Синтаксис полезен при работе с контроллером или репозиторием. Он однажды создан, и он создает все, от чего он зависит. Может быть только один контроллер, и он открывает только одно соединение с базой данных. Это позволяет избежать больших проблем при работе с ресурсами или переменными, к которым необходимо получить доступ из всего приложения.

Однако есть недостатки, такие как проверяемость. Когда класс использует синглтон, на поведение этого класса теперь влияет поведение одиночек.

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

Резюме

Вы должны следить за тем, как определять глобальные переменные и работать с одиночными точками. При надлежащем уходе должно возникнуть не так много проблем.

Ответ 3

Я не вижу ни одного недостатка этого подхода:

  • Вы можете использовать разные переменные для разных частей программы (- > Нет кодирования пространства имен, если вам это не нравится, я думаю)
  • Это короткий, красивый, простой в использовании и имеет смысл, когда вы его читаете. Model.shared.test() на самом деле не имеет смысла, если вы думаете об этом, вы просто хотите вызвать тест, почему мне нужно вызвать shared, когда мне просто нужна функция.
  • Он использует быстрое ленивое глобальное пространство имен: класс получает выделение и инициализируется, когда вы используете его в первый раз; если вы никогда не используете его, он даже не получает выделенное/включенное.

В целом, отложив в сторону обсуждаемую точную идиому, касающуюся использования синглетонов:

  • Напомним, что, конечно, вместо того, чтобы использовать static var shared = Model() как своего рода макрос в одноэлемент, как это предложено в этом Q, вы можете просто определить let model = Model(), который просто создает нормальный глобальный (не имеющий отношения к синглонам).
  • С Swift-синглонами обсуждалось, что, возможно, вы хотите добавить private init() {} в свой класс, чтобы он только инициализировался один раз (отмечая, что init все равно можно вызвать в том же файле).
  • Конечно, при рассмотрении использования singleton, если вам действительно не нужно состояние и сам экземпляр класса, вы можете просто использовать статические функции/свойства. Общей ошибкой является использование singleton (например, "расчетные" функции), где все, что требуется, является статическим методом.