How to understand this structure?

Asked

Viewed 1,197 times

2

ContactHelper.internal();

static final ContactHelper _instance = ContactHelper.internal();

factory ContactHelper() => _instance;

After an intense research on Factory methods and Singleton Pattern, I was able to understand the purpose of these standardizations, but I cannot understand the functioning of the above code made in Dart. I cannot assimilate an order of events, as it refers to the very instance already created or not, after all this is what happens?

1 answer

5


First let us clarify a few points about this question:

  • Construtores Privados

In Dart we can define private builders through the modifier _ as prefix. There is a natural convension of naming this constructor as _internal() but he might actually be _qualquerNome(), or even just _() This constructor defined as private is accessible only within the class itself, or lib that it belongs to.

  • Construtores Factory

This keyword is used to create constructs that do not always create a new instance of the class, but can instead return an instance of a previously created cache, or in this case a single instance used in the Singleton pattern. For example:

class Pessoa {
  final String nome;
  
  Pessoa._internal(this.nome);
  
  static final Map<String, Pessoa> _cachePessoas = {};
  
  factory Pessoa(String nome) {
    if(_cachePessoas.containsKey(nome)) {
      return _cachePessoas[nome];
    }
    
    final novaPessoa = Pessoa._internal(nome);
    _cachePessoas[nome] = novaPessoa;
    return novaPessoa;
  }
  
  static imprimirCache() {
    print(_cachePessoas);
  }
}

void main() {
  Pessoa('Elon Musk');
  Pessoa('Bill Gates');
  Pessoa('Elon Musk');
  Pessoa('Bill Gates');

  Pessoa.imprimirCache();  
}

Above simply note the functioning of Factory in conjunction with a private constructor to retrieve objects from a people cache, and when calling the same constructor the second time for the same person, a new instance is not created but an existing one is returned. Testing on the Dartpad.

  • Singletons in Dart

There are some ways to create a Singleton on Dart, where there is no better or worse.

  1. Singleton with Factory - Dartpad
class Pessoa {
  Pessoa._();

  static final Pessoa _instance = Pessoa._();

  factory Pessoa(){
    return _instance;
  }
}

main () {
  Pessoa um = Pessoa();
  Pessoa dois = Pessoa();
  print(identical(um, dois));
}

This is the example you used, uses a Factory constructor and another private constructor to ensure that there will be only one instance of the Person class. What’s going on is that:

Our _instance is Static, so it belongs to the class, not to the object.

Since it is a member of the class, with the end, we indicate that it should be initialized, so we initialize through the private constructor _()

The ending also ensures that this value will not be modified during the execution of the program, thus having our Singleton guaranteed.

With that, when calling Pessoa(), just return the previously created instance, ensuring that it will always be the same.

Note that whoever calls this class does not know whether or not it is a Singleton, as it is only calling Pessoa() that could always be creating a new Normal instance. So this approach can be used when you don’t want anyone to know that you are a Singleton, or even intend to change this implementation in the future to stop being a Singleton without breaking the code of the caller.

  1. Singleton with get - Dartpad
class Pessoa {
  Pessoa._();

  static final Pessoa _instance = Pessoa._();

  static Pessoa get instance { return _instance;}
}

main () {
  Pessoa um = Pessoa.instance;
  Pessoa dois = Pessoa.instance;
  print(identical(um, dois));
}

Another approach similar to previous but without Factory, we are now accessing the instance through a get, so whoever uses our Singleton knows explicitly that he is a Singleton. Our private builder again guarantees that there will be no other way to instantiate a new Person, where the only alternative is the use of the instance that we make available.

  1. Singleton with Static member - Dartpad
class Pessoa {
  Pessoa._();

  static final Pessoa instance = Pessoa._();
}

main () {
  Pessoa um = Pessoa.instance;
  Pessoa dois = Pessoa.instance;
  print(identical(um, dois));
}

With a small change in the previous approach, we have a shorter new form. The only difference is that now our instance is no longer private, and can be accessed directly without the need for a get. It is the one that requires fewer lines of code, however, is the only one that does not allow something to be done if always before someone accesses our instance.

Is answered? (:

  • 1

    Well explained, thank you for your reply, there was only one question about this last way to create a Singleton, more specifically when you say "it is the only one that does not allow something to be done always before someone accesses our instance", so I understand, it does not allow us to initialize it with previous validations or methods, I am correct?

  • 2

    @jsdaniell Imagine that you want to count how many times the instance is called (or do anything else). In the first you can increase the Count in the Factory constructor, in the second you can increase in the get, in the third it is not possible because the instance is accessed directly.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.