Padrão Singleton
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 65 de 87.
O Singleton Pattern é um padrão de projeto criacional que garante que uma classe tenha apenas uma instância em toda a sua aplicação, além de fornecer um ponto de acesso global a essa instância. Isso é útil para recursos que devem ser compartilhados, como gerenciadores de configuração, pools de conexão ou serviços de registro.
O padrão funciona tornando o construtor privado, impedindo a instanciação direta. Em vez disso, um método estático controla o acesso à única instância:
public class DatabaseConnection {
private static DatabaseConnection instance;
// Construtor privado impede a instanciação direta
private DatabaseConnection() {
System.out.println("Connection created");
}
// Ponto de acesso global
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
public void query(String sql) {
System.out.println("Executing: " + sql);
}
}Cada chamada a getInstance() retorna o mesmo objeto. A instância é criada somente quando solicitada pela primeira vez. Isso é chamado de inicialização tardia:
DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();
System.out.println(db1 == db2); // true - same instanceOs principais componentes de um Singleton são: um campo private static que armazena a instância, um construtor private e um método public static que retorna a instância. Essa combinação garante que, não importa quantas vezes você solicite o objeto, sempre obterá o mesmo.
Desafio
FácilVamos criar um gerenciador de configuração para uma aplicação usando o Padrão Singleton! Seu gerenciador de configuração garantirá que todas as partes da sua aplicação compartilhem as mesmas configurações, não importa quantas vezes solicitem acesso a elas.
Você organizará seu código em dois arquivos:
AppConfig.java: crie uma classe Singleton que gerencie as configurações da aplicação. SeuAppConfigdeve ter:Um campo estático privado para armazenar a única instância.
Um campo privado do tipo String chamado
appNamee um campo privado do tipo int chamadomaxUsers.Um construtor privado que inicialize
appNamecom"MyApplication"emaxUserscom100, e depois imprimaAppConfig initialized.Um método estático público
getInstance()que crie a instância somente se ela ainda não existir (inicialização tardia) e depois a retorne.Um método
setAppName(String name)que atualize o nome da aplicação.Um método
setMaxUsers(int max)que atualize o número máximo de usuários.Um método
displaySettings()que imprimaApp: [appName], Max Users: [maxUsers].Main.java: demonstre que seu Singleton funciona corretamente! Você receberá duas entradas: um novo nome de aplicação (String) e um novo valor máximo de usuários (inteiro).Primeiro, obtenha uma instância de
AppConfige armazene-a em uma variável chamadaconfig1. ChamedisplaySettings()para exibir os valores padrão.Em seguida, atualize as configurações usando os valores de entrada, chamando
setAppNameesetMaxUsersemconfig1.Obtenha outra instância e armazene-a em
config2. ChamedisplaySettings()emconfig2para provar que ela reflete as alterações feitas por meio deconfig1.Por fim, imprima se ambas as referências apontam para o mesmo objeto:
Same instance: [true/false], comparandoconfig1 == config2.
Você receberá duas entradas, nesta ordem: o novo nome da aplicação (String) e o novo número máximo de usuários (inteiro).
Este desafio demonstra o principal benefício do Padrão Singleton: não importa quantas vezes você solicite a configuração, sempre obterá a mesma instância com o mesmo estado compartilhado!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler entradas
String newAppName = scanner.nextLine();
int newMaxUsers = scanner.nextInt();
// TODO: Obtenha a primeira instância de AppConfig e armazene em config1
// TODO: Chame displaySettings() em config1 para mostrar os valores padrão
// TODO: Atualize as configurações usando setAppName e setMaxUsers em config1
// TODO: Obtenha outra instância e armazene em config2
// TODO: Chame displaySettings() em config2 para provar que as alterações são compartilhadas
// TODO: Imprima se ambas as referências apontam para o mesmo objeto:
// "Same instance: [true/false]" using config1 == config2
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online