paint-brush
Descubra o padrão de aliasby@raffaeleflorio
1,347
1,347

Descubra o padrão de alias

O padrão Alias lida com dois problemas. A primeira é estender a forma como uma classe final constrói seus objetos. O segundo é ter muitos construtores com os mesmos parâmetros, mas semântica diferente. Ao fazê-lo, promove a composição do objeto sobre a herança. De fato, não requer subclasse nem alteração do código da classe afetada. Em certo grau, pode ser visto como uma forma de decorar a construção de objetos.

Company Mentioned

Mention Thumbnail
featured image - Descubra o padrão de alias
Raffaele Florio HackerNoon profile picture


Enquanto escrevo código OOP, aplico algumas práticas de Objetos Elegantes.


Uma delas é que as aulas devem ser definitivas. Isso significa que eles não podem ser estendidos por herança, mas apenas por composição.


A vantagem é a simplicidade. Quero dizer que, dessa forma, cada objeto é visto como um bloco coeso. O que interessa aos seus clientes é o seu comportamento exposto. Nada mais. Em vez disso, por meio da extensão, um cliente pode quebrá-lo.


Por exemplo, um objeto pode inter-relacionar dois de seus métodos. Então, se pudermos substituir por extensão um deles, podemos quebrar o outro. Por esta razão, para ter certeza, devemos verificar sua implementação. Desta forma, aumentamos o acoplamento entre o estendido e a extensão.


Em outras palavras, as classes finais reforçam a ideia de que devemos nos preocupar apenas com o comportamento exposto. E não de implementação. No entanto, requer uma mudança de como raciocinamos sobre eles. O padrão Alias simplifica um aspecto dessa mudança.

Intenção

O padrão Alias permite estender a maneira como uma classe pode construir seus objetos sem criar subclasses ou modificá-los.

Motivação

Suponha uma classe final que cria seus objetos usando alguns parâmetros obrigatórios. Como podemos adicionar outra maneira de criar seus objetos? Por exemplo, como podemos adicionar um construtor que usa um valor padrão para um ou mais de seus parâmetros ausentes?


Uma abordagem poderia ser adicionar outro construtor à classe. Mas isso pode sair do controle. Além disso, pode não ser possível. Por exemplo, a classe final acima mencionada pode estar em uma biblioteca externa.


Outra desvantagem dessa abordagem é que podemos poluir a classe final. Por exemplo, podemos ter uma classe final que constrói seus objetos a partir de um JSON. Mas depois de algum tempo precisamos adicionar também XML. Como você pode imaginar, adicionar o código para mapear XML para JSON poluirá inevitavelmente essa classe.


No entanto, o padrão Alias não se limita às classes finais. Por exemplo, não podemos ter dois construtores com os mesmos parâmetros, mas semântica diferente.


Para resolver esse problema, podemos adicionar métodos de fábrica estáticos ao código da classe. Mas as mesmas desvantagens mencionadas afetam essa abordagem. Ou seja: isso foge do controle; isso não pode ser sempre possível; isso vai poluir a classe.


Uma abordagem melhor para ambos os problemas é criar outra classe com o comportamento de construtor desejado. Essa classe encapsula sua própria lógica de construção. E delegará tudo para a outra classe, inclusive a própria criação. Este é o padrão Alias.

Aplicabilidade

Use o padrão Alias quando:


  • Você precisa adicionar ou modificar um construtor de uma classe final;


  • Você deseja adicionar ou modificar um construtor de uma classe sem modificá-lo ou subclasse;


  • Você precisa de dois ou mais construtores de uma classe com os mesmos parâmetros sem modificá-lo ou subclasse.

Estrutura

A estrutura é simples. Precisamos de pelo menos duas classes que implementem a mesma interface: um Alias e um Aliased.


participantes


  • AnInterface
    • declara uma interface.


  • Aliased
    • implementa AnInterface ;

    • expõe um ou mais construtores.


  • Alias
    • implementa AnInterface ;
    • expõe um ou mais construtores;
    • mantém uma referência a um objeto Aliased ;
    • delega tudo ao objeto Aliased referenciado.

Colaboração

  • Alias constrói - de acordo com suas próprias regras - um objeto Aliased e mantém uma referência dele. Em seguida, ele delega tudo ao aliased.


Consequências


O padrão Alias tem as seguintes consequências:


  • Permite adicionar ou modificar construtores facilmente;
  • Promove a composição sobre a herança;
  • Aumenta o número de aulas;
  • Reduz a duplicação de código quando usado para substituir uma criação recorrente;
  • As classes de alias duplicam o código de delegação. Se isso for um problema, pode-se abordá-lo com uma classe Alias abstrata básica.

Implementação

Para implementar o padrão Alias você precisa:


  1. definir uma interface;

  2. para implementar a interface definida anteriormente com uma classe. Este será o alias;

  3. para implementar a interface definida anteriormente com uma classe de alias, e você precisa:

    1. definir um construtor que construa um objeto alias de acordo com algumas necessidades;
    2. uma variável de instância privada que faz referência ao objeto com alias criado anteriormente;
    3. para delegar tudo ao objeto com alias.

Código de amostra

O código Java-ish abaixo expressa o padrão Alias. Neste código, o alias injeta um valor padrão para um parâmetro obrigatório:


 interface AnInterface { void aMethod(); Something anotherMethod(); } final class Aliased implements AnInterface { private final A a; private final B b; Aliased(final A a, final B b) { this.a = a; this.b = b; } void aMethod() { // implementation } Something anotherMethod() { // implementation } } final class Alias implements AnInterface { private final Aliased aliased; Alias(final A a) { this( new Aliased( a, new InstanceOfB(...) ) ); } private Alias(final Aliased aliased) { this.aliased = aliased; } void aMethod() { this.aliased.aMethod(); } Something anotherMethod() { return this.aliased.anotherMethod(); } }


Padrões Relacionados

Até certo ponto, o padrão Alias também pode ser visto como uma forma de decorar a construção dos objetos. Essa visão é especialmente verdadeira se vemos uma classe como um objeto cuja responsabilidade é criar objetos.