SIGLETON
4 participantes
Página 1 de 1
SIGLETON
Algum tutorial bacana de com usar Sigleton e para que servem?
Throf- Iniciante
- PONTOS : 1787
REPUTAÇÃO : 0
Respeito as regras :
Re: SIGLETON
https://refactoring.guru/pt-br/design-patterns/singleton/csharp/example#example-0
Weslley- Moderador
- PONTOS : 5727
REPUTAÇÃO : 744
Idade : 26
Áreas de atuação : Inversión, Desarrollo, Juegos e Web
Respeito as regras :
Re: SIGLETON
Aqui um Mini-Tutorial sobre Singleton:
O Singleton é um padrão de projeto muito útil se você quiser criar um ponto de acesso global entre todas as classes existentes dentro de um sistema.
Na verdade já existe em C# um mecanismo nativo que faz isso, são as classes estáticas.
Vamos supor que você tenha uma classe de GameManager que guarda as variáveis das informações do jogo, como vidas do jogador, index da fase atual, dinheiro e etc.
Se um inimigo na cena retira vida do jogador, ele deve fazer acesso à variável de vida para retirá-la, bem como se ele for destruído pelo player, ele pode acrescer o valor de dinheiro do jogador, também tendo que fazer acesso a essa variável.
Aqui entramos em dois impasses: Ou faz acesso dessas variáveis através do FindObjectOfType para recuperar o objeto na cena do tipo "GameManager", ou qualquer outro tipo de referência, fazendo assim acesso a essas variáveis, ou podemos simplesmente criar a classe GameManager como estática e guardar esses valores estaticamente, nos livrando assim do FindObjectOfType e os problemas que ele pode nos trazer.
A classe seria assim:
Até parece um cenário ideal, pois para acessar uma variável do GameManager basta fazer:
O próprio .Net se utiliza de uma classe estática em suas entranhas para algo muito corriqueiro para nós programadores, a classe "Math", utilizada para realizar cálculos matemáticos, como por exemplo, realizar a potenciação de um número:
Math.Pow(60, 2);
Outra classe estática muito útil para aplicações console no .net é literalmente "Console", para escrever e ler informações:
Console.WriteLine("Teste");
E assim por diante...
Mas as classes estáticas trazem consigo algumas desvantagens: Não podem herdar de outras classes ou implementar interfaces (o que é um grande problema se precisamos de uma classe que herde de MonoBehaviour no Unity) e na questão da programação assicrona, não temos um controle da inicialização dessa classe.
Se quiser ler mais sobre as diferenças entre singleton e static class, recomendo esse link: https://stackoverflow.com/questions/519520/difference-between-static-class-and-singleton-pattern
Enfim, para acabar com essas desvantagens, temos o pattern Singleton, que se comporta como uma static class (tendo um acesso global, sem precisar de referências), porém com diversos benefícios mediante às classes estáticas:
A classe singleton pode implementar interfaces ou herdar de outras classes, se comporta realmente como um objeto para o compiler (podendo ser passada como argumento de um método, por exemplo), e pode ser inicializada assicronamente, como mostrado no link sugerido do membro acima.
Se uma classe singleton se comporta como um object (porque de fato é um), todos os princípios da programação orientada a objetos como polimorfismo e herança principalmente podem ser aplicados a ela, o que é muito vantajoso por si só.
Na verdade singleton é uma classe de instância (não estática) mas o diferencial dela é que ela tem uma instância única durante toda a vida da aplicação, essa instância é armazenada numa variável estética, e só ela deve existir no programa todo, criando assim, o ponto global de acesso.
Na Unity podemos usar a classe singleton para possuir os benefícios de métodos como Start, Update, FixedUpdate, Coroutines, Invoke, OnDestroy, OnEnable e Awake, que só podem funcionar corretamente quando a classe herda de MonoBehaviour.
Para criar uma classe que implete o padrão singleton, você precisa garantir que ela exista em todas as cenas do projeto e que sua instância (no caso da Unity, objeto da cena) seja único.
Veja a implementação de uma simples classe singleton dentro da Unity (herdando de MonoBehaviour):
No exemplo acima criamos uma classe normalmente, e dentro dela uma variável do tipo static que vai armazenar a única instância desse objeto, por isso dentro do get dessa variável, verifica-se se essa instância já existe na cena, se sim, ele apenas retorna a própria, se não, ele cria essa instância a partir do Find, encontrando o objeto na cena do tipo "GameManager".
Então dentro da variável "Instance" vai ser armazenado o objeto GameManager da cena, e isso vai servir para todas as cenas, já que no Awake do objeto demos a instrução dele não ser destruído quando a cena é carregada.
Por fim, para acessar globalmente as variáveis e métodos dessa classe, basta fazer o seguinte:
E agora temos os benefícios do ponto de acesso global, não precisa instanciar esse objeto para guardar informações globais e únicas, tudo isso podendo aplicar os fundamentos da POO e boas práticas da programação assicrona (caso esteja utilizando).
Mas bem, tudo não são flores, o singleton possui algumas desvantagens, dentre as mais notáveis:
>> Difícil depurar um sistema com singleton;
>> Dependência. Se o sistema se utiliza muito de informações contidas numa classe singleton, ele acaba se tornando dependente desta;
>> Vai contra (ironicamente) os princípios da POO e o princípio SOLID, do código escalavel e limpo (pelos motivos apresentados acima);
>> Se não for aplicado corretamente pode ser unsafe numa aplicação assicrona.
Mas é isso, tem que saber usar com moderação e de acordo com a sua necessidade, não podes criar uma aplicação toda baseada em singleton, existem outros patterns que podem te ajudar com algum problema específico em que você pense que deve ser solucionado com singleton mas não é a única solução, basta pesquisar mais e aprender a estruturar corretamente as suas classes.
O Singleton é um padrão de projeto muito útil se você quiser criar um ponto de acesso global entre todas as classes existentes dentro de um sistema.
Na verdade já existe em C# um mecanismo nativo que faz isso, são as classes estáticas.
Vamos supor que você tenha uma classe de GameManager que guarda as variáveis das informações do jogo, como vidas do jogador, index da fase atual, dinheiro e etc.
Se um inimigo na cena retira vida do jogador, ele deve fazer acesso à variável de vida para retirá-la, bem como se ele for destruído pelo player, ele pode acrescer o valor de dinheiro do jogador, também tendo que fazer acesso a essa variável.
Aqui entramos em dois impasses: Ou faz acesso dessas variáveis através do FindObjectOfType para recuperar o objeto na cena do tipo "GameManager", ou qualquer outro tipo de referência, fazendo assim acesso a essas variáveis, ou podemos simplesmente criar a classe GameManager como estática e guardar esses valores estaticamente, nos livrando assim do FindObjectOfType e os problemas que ele pode nos trazer.
A classe seria assim:
- Código:
using System.Collections;
using System;
public static class GameManager {
public static int lifes, coins, currentScene;
}
Até parece um cenário ideal, pois para acessar uma variável do GameManager basta fazer:
- Código:
GameManager.coins += 2500;
O próprio .Net se utiliza de uma classe estática em suas entranhas para algo muito corriqueiro para nós programadores, a classe "Math", utilizada para realizar cálculos matemáticos, como por exemplo, realizar a potenciação de um número:
Math.Pow(60, 2);
Outra classe estática muito útil para aplicações console no .net é literalmente "Console", para escrever e ler informações:
Console.WriteLine("Teste");
E assim por diante...
Mas as classes estáticas trazem consigo algumas desvantagens: Não podem herdar de outras classes ou implementar interfaces (o que é um grande problema se precisamos de uma classe que herde de MonoBehaviour no Unity) e na questão da programação assicrona, não temos um controle da inicialização dessa classe.
Se quiser ler mais sobre as diferenças entre singleton e static class, recomendo esse link: https://stackoverflow.com/questions/519520/difference-between-static-class-and-singleton-pattern
Enfim, para acabar com essas desvantagens, temos o pattern Singleton, que se comporta como uma static class (tendo um acesso global, sem precisar de referências), porém com diversos benefícios mediante às classes estáticas:
A classe singleton pode implementar interfaces ou herdar de outras classes, se comporta realmente como um objeto para o compiler (podendo ser passada como argumento de um método, por exemplo), e pode ser inicializada assicronamente, como mostrado no link sugerido do membro acima.
Se uma classe singleton se comporta como um object (porque de fato é um), todos os princípios da programação orientada a objetos como polimorfismo e herança principalmente podem ser aplicados a ela, o que é muito vantajoso por si só.
Na verdade singleton é uma classe de instância (não estática) mas o diferencial dela é que ela tem uma instância única durante toda a vida da aplicação, essa instância é armazenada numa variável estética, e só ela deve existir no programa todo, criando assim, o ponto global de acesso.
Na Unity podemos usar a classe singleton para possuir os benefícios de métodos como Start, Update, FixedUpdate, Coroutines, Invoke, OnDestroy, OnEnable e Awake, que só podem funcionar corretamente quando a classe herda de MonoBehaviour.
Para criar uma classe que implete o padrão singleton, você precisa garantir que ela exista em todas as cenas do projeto e que sua instância (no caso da Unity, objeto da cena) seja único.
Veja a implementação de uma simples classe singleton dentro da Unity (herdando de MonoBehaviour):
- Código:
public class GameManager: MonoBehaviour {
private static GameManager _instance;
public static GameManager Instance {
get{
if(_instance == null) {
_instance = GameObject.FindObjectOfType<GameManager>();
}
return _instance;
}
}
// Variáveis de acesso:
public int Coins {get; set;}
public int Lifes {get; set;}
}
void Awake(){
DontDestroyOnLoad(gameObject);
}
}
No exemplo acima criamos uma classe normalmente, e dentro dela uma variável do tipo static que vai armazenar a única instância desse objeto, por isso dentro do get dessa variável, verifica-se se essa instância já existe na cena, se sim, ele apenas retorna a própria, se não, ele cria essa instância a partir do Find, encontrando o objeto na cena do tipo "GameManager".
Então dentro da variável "Instance" vai ser armazenado o objeto GameManager da cena, e isso vai servir para todas as cenas, já que no Awake do objeto demos a instrução dele não ser destruído quando a cena é carregada.
Por fim, para acessar globalmente as variáveis e métodos dessa classe, basta fazer o seguinte:
- Código:
GameManager.Instance.Lifes += 2;
GameManager.Instance.Coins += 100;
E agora temos os benefícios do ponto de acesso global, não precisa instanciar esse objeto para guardar informações globais e únicas, tudo isso podendo aplicar os fundamentos da POO e boas práticas da programação assicrona (caso esteja utilizando).
Mas bem, tudo não são flores, o singleton possui algumas desvantagens, dentre as mais notáveis:
>> Difícil depurar um sistema com singleton;
>> Dependência. Se o sistema se utiliza muito de informações contidas numa classe singleton, ele acaba se tornando dependente desta;
>> Vai contra (ironicamente) os princípios da POO e o princípio SOLID, do código escalavel e limpo (pelos motivos apresentados acima);
>> Se não for aplicado corretamente pode ser unsafe numa aplicação assicrona.
Mas é isso, tem que saber usar com moderação e de acordo com a sua necessidade, não podes criar uma aplicação toda baseada em singleton, existem outros patterns que podem te ajudar com algum problema específico em que você pense que deve ser solucionado com singleton mas não é a única solução, basta pesquisar mais e aprender a estruturar corretamente as suas classes.
Re: SIGLETON
MayLeone escreveu:Aqui um Mini-Tutorial sobre Singleton:
O Singleton é um padrão de projeto muito útil se você quiser criar um ponto de acesso global entre todas as classes existentes dentro de um sistema.
Na verdade já existe em C# um mecanismo nativo que faz isso, são as classes estáticas.
Vamos supor que você tenha uma classe de GameManager que guarda as variáveis das informações do jogo, como vidas do jogador, index da fase atual, dinheiro e etc.
Se um inimigo na cena retira vida do jogador, ele deve fazer acesso à variável de vida para retirá-la, bem como se ele for destruído pelo player, ele pode acrescer o valor de dinheiro do jogador, também tendo que fazer acesso a essa variável.
Aqui entramos em dois impasses: Ou faz acesso dessas variáveis através do FindObjectOfType para recuperar o objeto na cena do tipo "GameManager", ou qualquer outro tipo de referência, fazendo assim acesso a essas variáveis, ou podemos simplesmente criar a classe GameManager como estática e guardar esses valores estaticamente, nos livrando assim do FindObjectOfType e os problemas que ele pode nos trazer.
A classe seria assim:
- Código:
using System.Collections;
using System;
public static class GameManager {
public static int lifes, coins, currentScene;
}
Até parece um cenário ideal, pois para acessar uma variável do GameManager basta fazer:
- Código:
GameManager.coins += 2500;
O próprio .Net se utiliza de uma classe estática em suas entranhas para algo muito corriqueiro para nós programadores, a classe "Math", utilizada para realizar cálculos matemáticos, como por exemplo, realizar a potenciação de um número:
Math.Pow(60, 2);
Outra classe estática muito útil para aplicações console no .net é literalmente "Console", para escrever e ler informações:
Console.WriteLine("Teste");
E assim por diante...
Mas as classes estáticas trazem consigo algumas desvantagens: Não podem herdar de outras classes ou implementar interfaces (o que é um grande problema se precisamos de uma classe que herde de MonoBehaviour no Unity) e na questão da programação assicrona, não temos um controle da inicialização dessa classe.
Se quiser ler mais sobre as diferenças entre singleton e static class, recomendo esse link: https://stackoverflow.com/questions/519520/difference-between-static-class-and-singleton-pattern
Enfim, para acabar com essas desvantagens, temos o pattern Singleton, que se comporta como uma static class (tendo um acesso global, sem precisar de referências), porém com diversos benefícios mediante às classes estáticas:
A classe singleton pode implementar interfaces ou herdar de outras classes, se comporta realmente como um objeto para o compiler (podendo ser passada como argumento de um método, por exemplo), e pode ser inicializada assicronamente, como mostrado no link sugerido do membro acima.
Se uma classe singleton se comporta como um object (porque de fato é um), todos os princípios da programação orientada a objetos como polimorfismo e herança principalmente podem ser aplicados a ela, o que é muito vantajoso por si só.
Na verdade singleton é uma classe de instância (não estática) mas o diferencial dela é que ela tem uma instância única durante toda a vida da aplicação, essa instância é armazenada numa variável estética, e só ela deve existir no programa todo, criando assim, o ponto global de acesso.
Na Unity podemos usar a classe singleton para possuir os benefícios de métodos como Start, Update, FixedUpdate, Coroutines, Invoke, OnDestroy, OnEnable e Awake, que só podem funcionar corretamente quando a classe herda de MonoBehaviour.
Para criar uma classe que implete o padrão singleton, você precisa garantir que ela exista em todas as cenas do projeto e que sua instância (no caso da Unity, objeto da cena) seja único.
Veja a implementação de uma simples classe singleton dentro da Unity (herdando de MonoBehaviour):
- Código:
public class GameManager: MonoBehaviour {
private static GameManager _instance;
public static GameManager Instance {
get{
if(_instance == null) {
_instance = GameObject.FindObjectOfType<GameManager>();
}
return _instance;
}
}
// Variáveis de acesso:
public int Coins {get; set;}
public int Lifes {get; set;}
}
void Awake(){
DontDestroyOnLoad(gameObject);
}
}
No exemplo acima criamos uma classe normalmente, e dentro dela uma variável do tipo static que vai armazenar a única instância desse objeto, por isso dentro do get dessa variável, verifica-se se essa instância já existe na cena, se sim, ele apenas retorna a própria, se não, ele cria essa instância a partir do Find, encontrando o objeto na cena do tipo "GameManager".
Então dentro da variável "Instance" vai ser armazenado o objeto GameManager da cena, e isso vai servir para todas as cenas, já que no Awake do objeto demos a instrução dele não ser destruído quando a cena é carregada.
Por fim, para acessar globalmente as variáveis e métodos dessa classe, basta fazer o seguinte:
- Código:
GameManager.Instance.Lifes += 2;
GameManager.Instance.Coins += 100;
E agora temos os benefícios do ponto de acesso global, não precisa instanciar esse objeto para guardar informações globais e únicas, tudo isso podendo aplicar os fundamentos da POO e boas práticas da programação assicrona (caso esteja utilizando).
Mas bem, tudo não são flores, o singleton possui algumas desvantagens, dentre as mais notáveis:
>> Difícil depurar um sistema com singleton;
>> Dependência. Se o sistema se utiliza muito de informações contidas numa classe singleton, ele acaba se tornando dependente desta;
>> Vai contra (ironicamente) os princípios da POO e o princípio SOLID, do código escalavel e limpo (pelos motivos apresentados acima);
>> Se não for aplicado corretamente pode ser unsafe numa aplicação assicrona.
Mas é isso, tem que saber usar com moderação e de acordo com a sua necessidade, não podes criar uma aplicação toda baseada em singleton, existem outros patterns que podem te ajudar com algum problema específico em que você pense que deve ser solucionado com singleton mas não é a única solução, basta pesquisar mais e aprender a estruturar corretamente as suas classes.
Não gostarias de copiar essa sua mensagem e criar um tópico de tutorial nos tutoriaisDosMembros??? É meio que um tutorial extremamente útil, que tira uma dúvida básica de várias pessoas, e ainda apresenta vantagens e desvantagens... Gostei bastante da resposta.
Re: SIGLETON
Obrigada Marcos, vou criar um tutorial mais organizado,. porém com base nessa reposta, pra deixar mais fácil de entender!
Re: SIGLETON
MayLeone escreveu:Obrigada Marcos, vou criar um tutorial mais organizado,. porém com base nessa reposta, pra deixar mais fácil de entender!
Muito obrigado!!!
Página 1 de 1
Permissões neste sub-fórum
Não podes responder a tópicos