padrões de Design são soluções de nível de design para problemas recorrentes que nós engenheiros de software encontramos frequentemente. Não é código – repito, código❌. É como uma descrição sobre como lidar com esses problemas e projetar uma solução.
utilizar estes padrões é considerado uma boa prática, uma vez que o design da solução é bastante experimentado e testado, resultando em maior legibilidade do Código final., Padrões de Design são muitas vezes criados para e usados por linguagens OOP, como Java, em que a maioria dos exemplos a partir daqui serão escritos.
tipos de padrões de design
Existem cerca de 26 padrões atualmente descobertos (eu dificilmente acho que vou fazer todos eles…).estes 26 podem ser classificados em 3 tipos:
1. Criacional: estes padrões são projetados para instanciação de classe. Podem ser padrões de criação de classes ou padrões de criação de objetos.2. Estrutural: estes padrões são projetados com relação à estrutura e composição de uma classe., O principal objetivo da maioria destes padrões é aumentar a funcionalidade da(S) Classe (s) envolvida (s), sem alterar grande parte de sua composição.3. Comportamental: estes padrões são projetados dependendo de como uma classe se comunica com os outros.
neste post, vamos passar por um padrão básico de design para cada tipo Classificado.
Type 1: Creational – the Singleton Design Pattern
The Singleton Design Pattern is a Creational pattern, whose objective is to create only one instance of a class and to provide only one global access point to that object., Um exemplo comumente usado de tal classe em Java é o calendário, onde você não pode fazer uma instância dessa classe. Ele também usa seu próprio método getInstance()
para obter o objeto a ser usado.
Uma classe usando o singleton design pattern) incluirá,
- uma privada, Uma variável estática, segurando a única instância da classe.
- um construtor privado, por isso não pode ser instanciado em qualquer outro lugar.
- um método estático público, para retornar a instância única da classe.,
Existem muitas implementações diferentes do design singleton. Hoje, vou passar pelas implementações de;
1. Instanciação ansiosa
2. Instanciação preguiçosa
3. Instanciação segura de Thread
Eager Beaver
public class EagerSingleton {// create an instance of the class.private static EagerSingleton instance = new EagerSingleton();// private constructor, so it cannot be instantiated outside this class.private EagerSingleton() { }// get the only instance of the object created.public static EagerSingleton getInstance() {return instance;}}
Este tipo de instanciação acontece durante o carregamento da classe, como a instanciação da instância variável acontece fora de qualquer método. Isto representa uma desvantagem pesada se esta classe não está sendo usada de todo pela aplicação cliente. O plano de contingência, se esta classe não está sendo usada, é a instanciação preguiçosa.,
dias preguiçosos
não há muita diferença em relação à implementação acima. As principais diferenças são que a variável estática é inicialmente declarada nula, e é apenas instanciada dentro do id
método se – e somente se – a variável instância permanece nula no momento da verificação.
isto corrige um problema, mas outro ainda existe. E se dois clientes diferentes acederem à aula de Singleton ao mesmo tempo, até ao milissegundo?, Bem, eles vão verificar se a instância é nula ao mesmo tempo, e vai encontrá-la verdadeira, e assim irá criar duas instâncias da classe para cada pedido pelos dois clientes. Para corrigir isso, instanciação Thread seguro deve ser implementado.
(Thread) Safety is Key
In Java, the keyword synchronized is used on methods or objects to implement thread safety, so that only one thread will access a particular resource at one time. A instanciação de classe é colocada dentro de um bloco sincronizado de modo que o método só pode ser acessado por um cliente em um determinado momento.,
A sobrecarga para o método sincronizado é alta, e reduz o desempenho de toda a operação.
Por exemplo, se a variável instância já foi instanciada, então cada vez que qualquer cliente acessa o método getInstance()
, o método synchronized
é executado e o desempenho cai. Isto só acontece para verificar se o valor das variáveis
é nulo. Se ele descobre que é, ele deixa o método.
para reduzir esta sobrecarga, é usado o bloqueio duplo., The check is used before the synchronized
method as well, and if the value is null alone, does the synchronized
method run.
agora para a próxima classificação.
Type 2: Structural-the Decorator Design Pattern
i’m gonna give you a small scenario to give a better context to why and where you should use the Decorator Pattern.digamos que você tem um café, e como qualquer novato, você começa com apenas dois tipos de café simples, a mistura da casa e assado escuro., No seu sistema de facturação, havia uma classe para as diferentes misturas de café,que herda a classe abstrata bebida. As pessoas realmente começam a vir e ter o seu maravilhoso (embora amargo?) Cafe. Depois há os novatos do café que, Deus nos livre, querem açúcar ou leite. Que Travesti para o café!! ??
Agora você precisa ter esses dois add-ons também, tanto para o menu e, infelizmente, no sistema de faturamento. Originalmente, sua pessoa de TI vai fazer uma subclasse para ambos os cafés, um incluindo açúcar, o outro leite., Então, uma vez que os clientes estão sempre certos, diz-se estas temidas palavras:
“Posso obter um café com leite, com açúcar, por favor?”
???lá se vai o teu sistema de facturação a rir-se na tua cara outra vez. Bem, de volta à estaca zero …
A pessoa TI adiciona então café de leite com açúcar como outra subclasse para cada classe de café pai. O resto do mês é fácil de navegar, as pessoas fazendo fila para ter o seu café, você realmente ganhar dinheiro. ??mas espera, há mais!o mundo está contra você mais uma vez., Um concorrente abre-se do outro lado da rua, com não apenas 4 tipos de café, mas mais de 10 add-ons também! ?
Você compra todos esses e mais, para vender melhor café você mesmo, e só então lembre-se que você esqueceu de atualizar o sistema de faturamento adulterado. Você possivelmente não pode fazer o número infinito de subclasses para qualquer e todas as combinações de todos os add-ons, com as novas misturas de café também. Sem mencionar o tamanho do sistema final.??
tempo para investir realmente num sistema de facturação adequado., Você encontra pessoal de TI novo, que realmente sabe o que eles estão fazendo e eles dizem;
“Por que, isso será muito mais fácil e menor se ele usou o padrão decorador.o que é isso?
o padrão de design do decorador cai na categoria estrutural, que lida com a estrutura real de uma classe, seja por herança, composição ou ambos. O objetivo deste projeto é modificar a funcionalidade de um objeto em tempo de execução. Este é um dos muitos outros padrões de design que utilizam classes abstratas e interfaces com a composição para obter o resultado desejado.,vamos dar uma hipótese à Matemática.) para trazer tudo isso em perspectiva;
tomar 4 misturas de café e 10 add-ons. Se nós prendemos à geração de subclasses para cada combinação diferente de todos os add-ons para um tipo de café. Isso é;
(10-1)2 = 92 = 81 subclasses
subtraímos 1 dos 10, uma vez que você não pode combinar um add-on com outro do mesmo tipo, açúcar com açúcar soa estúpido. E isto é só por uma mistura de café. Multiplica esse 81 por 4 e recebes 324 subclasses diferentes!, Fale sobre toda essa codificação …
mas com o padrão decorador irá exigir apenas 16 classes neste cenário. Queres apostar?
Se a gente mapa o nosso cenário de acordo com o diagrama de classe acima, temos 4 classes para o 4 blends de café, 10 para cada add-on e 1 para o componente abstrato e mais 1 para o resumo decorador. Vês? 16!, Agora Entrega-me esses 100 dólares.?? (jk, mas ele não será recusado se dado… just saying)
Como você pode ver acima, assim como o concreto misturas de café são subclasses da bebida classe abstrata, o AddOn classe abstrata também herda seus métodos a partir dele. Os add-ons, que são suas subclasses, por sua vez herdam quaisquer novos métodos para adicionar funcionalidade ao objeto base quando necessário.
let’s get to coding, to see this pattern in use.,
primeiro para fazer a classe abstrata de bebidas, que todas as diferentes misturas de café herdarão de:
depois para adicionar ambas as classes de mistura de café Concreto.
A classe abstrata AddOn também herda da classe abstrata Beverage (mais sobre isso abaixo).
E agora implementações concretas desta classe abstrata:
Como você pode ver acima, nós podemos passar qualquer subclasse de Bebida para qualquer subclasse de AddOn, e obter o valor adicionado, bem como a descrição atualizada. E, uma vez que a classe AddOn é essencialmente de tipo de bebida, podemos passar um AddOn para outro AddOn., Desta forma, podemos adicionar qualquer número de add-ons a uma mistura de café específico.
agora para escrever algum código para testar isso.
O resultado final é:
Ele funciona! Fomos capazes de adicionar mais de um add-on a uma mistura de café e atualizar com sucesso o seu custo final e descrição, sem a necessidade de fazer subclasses infinitas para cada combinação add-on para todas as misturas de café.finalmente, para a última categoria.,
Type 3: Behavioral – the Command Design Pattern
a behavioral design pattern focus on how classes and objects communicate with each other. O foco principal do padrão de comando é inculcar um maior grau de acoplamento solto entre as partes envolvidas (leia: classes).o que é isso?
Acoplamento é a forma como duas (ou mais) classes que interagem entre si, bem, interagem. O cenário ideal quando essas classes interagem é que elas não dependem muito umas das outras. É um acoplamento solto., Assim, uma melhor definição para acoplamento solto seria, classes que estão interligadas, fazendo o menor uso um do outro.
a necessidade deste padrão surgiu quando os pedidos precisavam ser enviados sem conscientemente saber o que você está pedindo ou quem é o receptor.
neste padrão, a classe de invocação é dissociada da classe que realmente executa uma ação. A classe invoker só tem o método executável, que executa o comando necessário, quando o cliente o requisita.vejamos um exemplo básico do mundo real, a pedir uma refeição num restaurante chique., À medida que o fluxo vai, você dá o seu pedido (comando) para o garçom (invoker), que, em seguida, entregá-lo ao chef(receptor), para que você possa obter comida. Pode parecer simples … mas um pouco em código.
a ideia é bastante simples, mas o código gira em torno do nariz.,
O fluxo de operação no lado técnico é, você faz um concreto de comando, que implementa a interface de Comando, pedindo que o receptor a realizar uma ação, e enviar o comando para o chamador. O invocador é a pessoa que sabe quando dar este comando. O chef é o único que sabe o que fazer quando lhe é dado o comando/ordem específico., Então, quando o método de execução do invoker é executado, ele, por sua vez, faz com que o método de execução de objetos de comando para executar no receptor, completando assim as ações necessárias.,
o Que precisa para implementar;
- Uma interface de Comando
- Uma classe, a Fim de que implementa a interface de Comando
- Uma classe Garçom (chamador)
- Um Chef de classe (receptor)
Assim, a codificação vai como esta:
o Chef, o receptor
de Comando, a interface
public interface Command {public abstract void execute();}
Ordem, o concreto de comando
Garçom, o chamador
public class Waiter {private Order order;public Waiter(Order ord) {this.order = ord;}public void execute() {this.order.execute();}}
Você, o cliente
Como você pode ver acima, o Cliente faz uma Encomenda e define o Receptor como o Chef., A ordem é enviada ao garçom, que saberá quando executar a ordem (ou seja, quando dar ao chef a ordem de cozinhar). Quando o invoker é executado, o método de execução das ordens é executado no receptor (ou seja, o chef é dado o comando para cozinhar massa? ou fazer bolo?).,
Rápida recapitulação
neste post nós fomos através de:
- o Que é um padrão de projeto é realmente,
- Os diferentes tipos de padrões de projeto e por que eles são diferentes
- Um básicas comuns ou padrão de design para cada tipo
espero que tenha sido útil.
encontre o repo de código para o post, aqui.