Design Patern – Singleton

Então você já aprendeu como declarar uma classe, chamar um método e aplicar os conceitos de herança e polimorfismo (já né?). Parabéns você completou a primeira parte do aprendizado em programação orientada a objetos. Agora só falta mais uns 95% para poder ser considerado um Mestre Jedi em Orientação a Objetos.

Vamos ganhar mais um ponto porcentual e falarmos de Singleton.

Singleton é um Padrão de Projeto (ou do inglês Design Patern). Os padrões de projetos tem como objetivo o reuso do projeto (não de código). É o reuso de uma solução para um problema simples e comum dentro da programação orientada a objetos.

O problema do Singleton resolve é muito simples: criar uma classe que permita uma e somente uma instância da classe em questão.

Vamos discutir abaixo a solução clássica em ABAP.

Gist: https://gist.github.com/2174007

 

Descrevendo a Classe

A classe em que será aplicada o Singleton é a LCL_HELLO_SINGLETON. Vamos começar com a declaração dela pois ela já nos trás algumas novidades:

CLASS lcl_hello_singleton DEFINITION FINAL CREATE PRIVATE.

A classe precisa necessariamente ser final, ou seja, ela não aceitará que nenhuma outra classe herde dela. Não é possível criar uma subclass da LCL_HELLO_SINGLETON, pois isso seria uma brecha onde o usuário criaria uma subclasse e que não respeitaria a regra de não permitir mais de uma instância dela.

A classe LCL_HELLO_SINGLETON também deve ter a sua regra de instanciação como privada. Isso significa que um objeto dessa classe somente pode ser criado dentro dela mesma. Isso garante o controle da criação dos objetos seja somente dela mesma. Nossa pequena classe é dona de seu próprio destino.

A segunda característica dessa classe é a presença de um construtor estático (método CLASS_CONSTRUCTOR). Um construtor estático é chamado apenas uma única vez durante toda a vida da classe. Ele difere do construtor da instância (método CONSTRUCTOR – não usado nesse exemplo) por ser chamado apenas uma única vez quando a classe é usada pela primeira vez (seja na criação de um objeto ou na chamada de um método estático – usado no exemplo). Um construtor de instância é chamado no momento da criação do objeto com o comando CREATE OBJECT.

O método estático GET_INSTANCE( ) é usado para retornar o valor que está no atributo estático R_INSTANCE, que é a referência do único objeto criado para essa classe.

O único objeto a existir para a classe LCL_HELLO_SINGLETON é criado no construtor estático e a sua referência é o R_INSTANCE.

Os métodos SET( ) e GET( ) são os chamados métodos de acessores, que servem para definir e retornar os atributos da classe, respectivamente.

Executando o Programa

Ao executar o programa, precisamos chamar o método estático GET_INSTANCE( ) para que a classe nos retorne a referência do objeto que ela mesma criou e está gerenciando. Mas nesse instante o objeto ainda não fora criado?! Erro na implementação do Padrão de Projeto!!! Calma…

A criação do objeto está no construtor estático que será chamado apenas uma única vez, quando a classe for usada. Sendo assim, quando chamarmos o método GET_INSTANCE( ) o construtor estático é chamado primeiro criando o objeto a ser retornado pelo parâmetro RE_INSTANCE( ). Genial? Não, programação orientada a objetos.

Agora todas as vezes que o programa precisar usar recuperar a referência do objeto filho único, ele deve chamar o método GET_INSTANCE( ).

Conclusão

Quando devemos usar um Singleton? A resposta é simples, economia de memória. Fato que um mesmo volume de dados representado em objetos pode consumir mais memória do que o seu equivalente em procedural, para uma boa ilustração disso, veja o post onde o Fábio fez uma comparação de consumo de memória entre uma tabela interna e os mesmos dados dessa tabela interna usando um objeto para cada linha da tabela.

Em geral, um programa ABAP manipulará os dados de duas maneiras, um Objeto de Negócio por vez, ou um conjunto de objetos por vez.

Em nossa vida de programador ABAP não é lá muito comum trabalharmos um objeto de negócio por vez, pois os programas standard já fazem isso. Geralmente trabalhamos um registro por vez quando estamos desenvolvendo algum module pool e os modules pools mais legais já foram feitos pela SAP.

A Claudia já comentou isso e é verdade, a maioria dos nossos programas são relatórios. E quando trabalharmos com relatórios invariavelmente seguimos a sequência, tela de seleção – seleção de dados – tratamento dos dados – apresentação dos dados. Então, quando estamos tratando os dados fazemos um LOOP AT na tabela interna e para cada registro a ser tratado usamos as regras de negócio encapsuladas nos métodos dessa classe. Portanto, não precisamos de todos os objetos criados ao mesmo tempo, apenas uma instância de nossa classe, sendo atualizada para cada registro a ser tratado.

You may also like...

2 Responses

  1. Alexandre de Jesus Carvalho says:

    Parabéns pelo post. Apenas outra possibilidade:

    A classe esta com o atribuído “CREATE PRIVATE”, com isso não poderá ser instanciada através do comando CREATE OBJECT.
    Desta forma você pode passar parâmetros no momento da criação.

    abs
    ex-aluno

    CLASS lcl_hello_singleton DEFINITION FINAL CREATE PRIVATE.

    PUBLIC SECTION.

    CLASS-METHODS get_intance
    RETURNING value(re_instance) TYPE REF TO lcl_hello_singleton.

    ENDCLASS.

    *———————————————————————-*
    * CLASS lcl_hello_singleton IMPLEMENTATION
    *———————————————————————-*
    *
    *———————————————————————-*
    CLASS lcl_hello_singleton IMPLEMENTATION.

    METHOD get_intance.

    IF r_instance IS INITIAL.
    CREATE OBJECT r_instance.
    ENDIF.

    re_instance = r_instance.

    ENDMETHOD.

    ENDCLASS.