JavaRush /Blogue Java /Random-PT /Adaptador de padrão de design

Adaptador de padrão de design

Publicado no grupo Random-PT
Olá! Hoje abordaremos um novo tópico importante - padrões, ou em outras palavras - padrões de design . O que são padrões? Acho que você conhece a expressão “não reinvente a roda”. Na programação, como em muitas outras áreas, existe um grande número de situações típicas. Para cada um deles, no processo de desenvolvimento da programação, foram criadas soluções de trabalho prontas. Estes são padrões de design. Relativamente falando, um padrão é um exemplo que oferece uma solução para uma situação como: “se o seu programa precisa fazer algo, qual a melhor forma de fazê-lo”. Existem muitos padrões, um excelente livro “Studying Design Patterns” é dedicado a eles, que você definitivamente deveria ler. Padrão de design "Adaptador" - 2Resumindo, um padrão consiste em um problema comum e sua solução, o que já pode ser considerado uma espécie de padrão. Na palestra de hoje conheceremos um desses padrões chamado “Adaptador”. Seu nome é revelador e você já encontrou adaptadores na vida real mais de uma vez. Um dos adaptadores mais comuns são os leitores de cartão, que são equipados com muitos computadores e laptops. Padrão de design "Adaptador" - 3Imagine que temos algum tipo de cartão de memória. Qual é o problema? O fato é que ela não sabe interagir com um computador. Eles não têm uma interface comum. O computador possui um conector USB, mas você não pode inserir um cartão de memória nele. O cartão não pode ser inserido no computador, por isso não poderemos salvar nossas fotos, vídeos e outros dados. O leitor de cartão é um adaptador que resolve esse problema. Afinal, ele possui um cabo USB! Ao contrário do cartão em si, o leitor de cartão pode ser inserido em um computador. Eles têm uma interface comum com um computador - USB. Vamos ver como ficaria com um exemplo:
public interface USB {

   void connectWithUsbCable();
}
Esta é a nossa interface USB, sendo o único método inserir o cabo USB:
public class MemoryCard {

   public void insert() {
       System.out.println("Карта памяти успешно вставлена!");
   }

   public void copyData() {
       System.out.println("Данные скопированы на компьютер!");
   }
}
Esta é a nossa classe que implementa o mapa de memória. Já possui 2 métodos que precisamos, mas aqui está o problema: não implementa a interface USB. O cartão não pode ser inserido no slot USB.
public class CardReader implements USB {

   private MemoryCard memoryCard;

   public CardReader(MemoryCard memoryCard) {
       this.memoryCard = memoryCard;
   }

   @Override
   public void connectWithUsbCable() {
       this.memoryCard.insert();
       this.memoryCard.copyData();
   }
}
E aqui está o nosso adaptador! O que a classeCardReader faz e por que é um adaptador? É simples. A classe que está sendo adaptada (mapa de memória) passa a ser um dos campos do adaptador. Isso é lógico, porque na vida real também inserimos um cartão dentro do leitor de cartão, e ele também passa a fazer parte dele. Ao contrário de um cartão de memória, o adaptador possui uma interface comum com o computador. Possui um cabo USB, o que significa que pode se conectar a outros dispositivos via USB. Portanto, no programa, nossa classe CardReaderimplementa a interface USB. Mas o que acontece dentro deste método? E acontece exatamente o que precisamos! O adaptador delega o trabalho ao nosso cartão de memória. Afinal, o adaptador em si não faz nada, o leitor de cartão não possui nenhuma funcionalidade independente. Sua função é apenas conectar o computador e o cartão de memória para que o cartão faça seu trabalho e copie arquivos! Nosso adaptador permite fazer isso fornecendo sua própria interface (método connectWithUsbCable()) para as “necessidades” do cartão de memória. Vamos criar algum tipo de programa cliente que irá simular uma pessoa que deseja copiar dados de um cartão de memória:
public class Main {

   public static void main(String[] args) {

       USB cardReader = new CardReader(new MemoryCard());
       cardReader.connectWithUsbCable();

   }
}
O que obtivemos como resultado? Saída do console:
Карта памяти успешно вставлена!
Данные скопированы на компьютер!
Ótimo, nossa tarefa foi concluída com sucesso! Aqui estão alguns links adicionais com informações sobre o padrão Adapter:

Aulas abstratas Leitor e Escritor

Agora voltaremos ao nosso passatempo favorito: aprenderemos algumas aulas novas para trabalhar com entrada e saída :) Quantas delas já aprendemos, me pergunto? Hoje falaremos sobre aulas Readere Writer. Por que sobre eles? Porque isso estará relacionado à nossa seção anterior - adaptadores. Vamos examiná-los com mais detalhes. Vamos começar com Reader'a. Readeré uma classe abstrata, portanto não poderemos criar explicitamente seus objetos. Mas na verdade você já o conhece! Afinal, as classes que você conhece bem BufferedReadersão InputStreamReadersuas herdeiras :)
public class BufferedReader extends Reader {}

public class InputStreamReader extends Reader {}
Portanto, uma classe InputStreamReaderé um adaptador clássico . Como você provavelmente se lembra, podemos passar um objeto para seu construtor InputStream. Na maioria das vezes usamos uma variável para isso System.in:
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
O que isso faz InputStreamReader? Como qualquer adaptador, ele converte uma interface em outra. Neste caso, a interface InputStream'a para a interface Reader' a. Inicialmente tivemos uma aula InputStream. Funciona bem, mas só pode ler bytes individuais. Além disso, temos uma classe abstrata Reader. Possui uma excelente funcionalidade que realmente precisamos - ele pode ler caracteres! É claro que realmente precisamos desta oportunidade. Mas aqui nos deparamos com um problema clássico que os adaptadores geralmente resolvem - incompatibilidade de interface. Como isso se manifesta? Vejamos diretamente a documentação do Oracle. Aqui estão os métodos da classe InputStream. Паттерн проектирования «Адаптер» - 4Um conjunto de métodos é uma interface. Como você pode ver, read()esta classe possui um método (mesmo em várias versões), mas só pode ler bytes: bytes individuais ou vários bytes usando um buffer. Esta opção não nos convém - queremos ler caracteres. A funcionalidade que precisamos já está implementada na classe abstrataReader . Isso também pode ser visto na documentação. Паттерн проектирования «Адаптер» - 5No entanto, as interfaces InputStream'a' e 'a' são incompatíveis! ReaderComo você pode ver, em todas as implementações de métodos, read()tanto os parâmetros passados ​​quanto os valores de retorno são diferentes. E é aqui que precisamos InputStreamReader! Ele atuará como um adaptador entre nossas aulas. Como no exemplo do leitor de cartões, que vimos acima, passamos o objeto da classe “adaptada” “internamente”, ou seja, para o construtor da classe adaptadora. No exemplo anterior, passamos um objeto MemoryCarddentro de CardReader. Agora passamos o objeto InputStreampara o construtor InputStreamReader! Como qualidade InputStreamusamos a variável já familiar System.in:
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
E de facto: olhando a documentação InputStreamReaderveremos que a “adaptação” foi bem sucedida :) Agora temos à nossa disposição métodos que nos permitem ler caracteres. Паттерн проектирования «Адаптер» - 6E embora inicialmente nosso objeto System.in(um thread vinculado ao teclado) não permitisse isso, ao criar o padrão Adapter , os criadores da linguagem resolveram esse problema. A classe abstrata Reader, como a maioria das classes de E/S, tem um irmão gêmeo - Writer. Tem a mesma grande vantagem Reader- fornece uma interface conveniente para trabalhar com símbolos. Com fluxos de saída, o problema e sua solução parecem iguais aos dos fluxos de entrada. Existe uma classe OutputStreamque só pode escrever bytes; Existe uma classe abstrata Writerque pode trabalhar com símbolos e existem duas interfaces incompatíveis. Este problema é novamente resolvido com sucesso pelo padrão Adaptador. Usando uma classe, OutputStreamWriterpodemos facilmente “adaptar” duas interfaces de classe uma Writerà OutputStreamoutra. E, tendo recebido um fluxo de bytes OutputStreamno construtor, com a ajuda OutputStreamWriterpodemos, porém, escrever caracteres, não bytes!
import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException {

       OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"));
       streamWriter.write(32144);
       streamWriter.close();
   }
}
Escrevemos um caractere com código 32144 - 綐 em nosso arquivo, eliminando assim a necessidade de trabalhar com bytes :) Por hoje é tudo, até as próximas palestras! :)
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION