Восстановление значений по умолчанию для объектов - PullRequest
0 голосов
/ 11 апреля 2019

Я использую два разных объекта, которые используются как синглтоны. В какой-то момент я хочу, чтобы пользователь мог снова выйти из системы и найти значения по умолчанию для объектов.

Есть ли лучший способ вместо переопределения значений, подобных этому?

objectA.variableA = ""
objectA.variableB = ""
objectA.variableC = ""

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

На мой взгляд, это не лучший способ использования «объекта». Если вы хотите создать какую-то сессию, лучше использовать сопутствующий объект класса. Для более чистой архитектуры лучше создать фабрику сессий с (im) изменяемыми состояниями.

class LoginSession private constructor(
    val variableA: String, // here you can also define default value
    val variableB: String,
    val variableC: String
) {

    companion object {
        fun create(a: String, b: String, c: String) = LoginSession(a, b, c)    
    }

}

Но, если вы настаиваете на том, что вам нужны синглтоны, вы можете изменить это решение следующим образом:

class LoginSession private constructor(
        val variableA: String, // here you can also define default value
        val variableB: String,
        val variableC: String
) {

    companion object {
        var instance: LoginSession? = null

        fun create(a: String, b: String, c: String) = if(instance != null) instance 
            else LoginSession(a, b, c).apply {
                    instance = this
                }

        fun reCreate(a: String, b: String, c: String): LoginSession? {
            instance = null
            return create(a, b, c)
        }

    }

}

Это решение может предоставить вам больше гибкости в вашем проекте, потому что вы можете манипулировать состоянием своего синглтона LoginSession по мере необходимости, без каких-либо последствий, таких как NPE или неправильные значения в var. Также, как мне кажется, этот код более чистый и масштабируемый.

U.P.D

Кроме того, я советую вам следовать рекомендациям Боба Мартина и Стива Макконнелла, в которых говорилось: «Если у вас есть более 2 аргументов в функциях / методах, попробуйте объединить их в 1 DTO (объект передачи данных)»

data class SessionDTO(val variableA: String, val variableB: String, val variableC: String)

class LoginSession private constructor(val session: SessionDTO) {

    companion object {
        var instance: LoginSession? = null

        fun create(session: SessionDTO) = if(instance != null) instance 
            else LoginSession(session).apply {
                    instance = this
                }

        fun reCreate(session: SessionDTO): LoginSession? {
            instance = null
            return create(session)
        }

    }

}

Итак, в этом случае у вас есть некоторые преимущества:

  • У вас есть неизменность без каких-либо побочных эффектов. Ваши данные имеют одно значение, доступное из любой части вашего приложения. Попробуйте использовать больше неизменяемости, как вы можете. Если одно из полей в SessionDTO изменится, вам придется заново создать сеанс входа в систему. И это правильно, потому что состояние вашего объекта изменилось. Прочитайте https://www.elegantobjects.org/,, это многое объясняет.
  • У вас есть гибкий и масштабируемый DTO, который вы можете изменить в любое время.
  • У вас есть ручное управление состоянием LoginSession. У вас есть возможность создать / воссоздать / уничтожить его экземпляр. Объект Котлина не дает вам этой точки.

В заключение я бы сказал, что Объекты не являются серебряной пулей. Он предназначен для создания простых синглетонов. И, думая, как инженер, вы должны выбрать правильный путь между базовыми реализациями и более сложными шаблонами. Например, ИМХО, лучший способ использовать объект Котлина (я взял его из книги «Котлин в действии» и немного изменил):

object Payroll {

   /*
       it's mocked method, imagine that inside it called network request, 
       or request in database, or from local storage(json-file, xml-file) 
       or something like this.
   */
   val employees: List<Employer>
       get() = Storage.loadAllEmployees() 

   /*
       So, you can in any time call method `calculateSalary` in any part
       of your application, and calculation algorithm will 
       evaluate salary for all current employers in system. 
   */
   fun calculateSalary() {
       for(person in employees) {
           // some evaluation algorithm 
       }  
   }
}
0 голосов
/ 12 апреля 2019

Объекты также могут иметь функции, поэтому я бы никогда не попытался сбросить состояние объекта до его начального состояния за пределами этого объекта. Скорее дайте ему функцию, которая сделает это за вас.

Кроме того, вы хотите убедиться, что функция сброса синхронизирована с тем, как вы инициализируете объект. Вы не хотите поддерживать семантику «по умолчанию» в 2 разных местах, будь то в объекте или вне его.

Итак, вот пример, который делает это:

object LoginSession {
    lateinit var variableA: String
    lateinit var variableB: String
    lateinit var variableC: String

    init {
        reset()
    }

    fun reset() {
        variableA = ""
        variableB = ""
        variableC = ""
    }
}

А теперь, если вы хотите сбросить состояние вашего объекта, вы можете просто позвонить LoginSession.reset()

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