Padrão de design do decorador
Eu posso me colocar em primeiro lugar, mesmo depois se eu quiser
Temos uma interface chamada Pagamento contém um método de pagamento .
E uma classe concreta DefaultPayment para implementar o método, o método pega o preço como argumento para fazer a lógica de pagamento.
public interface Payment {
void pay(BigDecimal price);
}
public class DefaultPayment implements Payment {
@Override
public void pay(BigDecimal price) {
System.out.println("Payed: " + price);
}
}
public class Client {
public static void main(String[] args) {
Payment defaultPayment = new DefaultPayment();
defaultPayment.pay(BigDecimal.valueOf(100));
}
}
Digamos que haja um imposto sobre um produto que desejo pagar, o que posso fazer?
Podemos aproveitar nosso design, projetamos para uma interface, não para uma implementação.
Assim, podemos criar uma classe para Payment e deixá-la ser um tipo de Payment e ao mesmo tempo manter o Payment como propriedade, podendo receber o pagamento usando seu construtor, e chamaremos essa classe de TaxPaymentDecorator .
public class TaxPaymentDecorator implements Payment {
private Payment payment;
private BigDecimal tax = BigDecimal.ZERO;
public TaxPaymentDecorator(Payment payment) {
this.payment = payment;
}
@Override
public void pay(BigDecimal price) {
price = price.add(this.tax);
payment.pay(price);
}
public BigDecimal getTax() {
return tax;
}
public void setTax(BigDecimal tax) {
this.tax = tax;
}
}
E o cliente poderia usar o TaxPaymentDecorator da seguinte forma:
public class Client {
public static void main(String[] args) {
TaxPaymentDecorator taxPaymentDecorator = new TaxPaymentDecorator(new DefaultPayment());
taxPaymentDecorator.setTax(BigDecimal.valueOf(50));
taxPaymentDecorator.pay(BigDecimal.valueOf(100));
}
}
public class DiscountPaymentDecorator implements Payment {
private Payment payment;
private BigDecimal discount = BigDecimal.ZERO;
public DiscountPaymentDecorator(Payment payment) {
this.payment = payment;
}
@Override
public void pay(BigDecimal price) {
price = price.subtract(discount);
payment.pay(price);
}
public BigDecimal getDiscount() {
return discount;
}
public void setDiscount(BigDecimal discount) {
this.discount = discount;
}
}
public class Client {
public static void main(String[] args) {
TaxPaymentDecorator taxPaymentDecorator = new TaxPaymentDecorator(new DefaultPayment());
taxPaymentDecorator.setTax(BigDecimal.valueOf(50));
DiscountPaymentDecorator discountPaymentDecorator = new DiscountPaymentDecorator(taxPaymentDecorator);
discountPaymentDecorator.setDiscount(BigDecimal.valueOf(10));
discountPaymentDecorator.pay(BigDecimal.valueOf(100));
}
}
Diagrama UML
Princípios de design
Vou discutir três princípios de design aqui:
- Design para uma interface não para implementação: Como você pode ver, usar a interface Payment nos ajudou a usar o poder do OOP adicionando comportamento dinamicamente no tempo de execução sem nenhuma modificação para a implementação antiga.
- Faça seu design aberto para extensão e fechado para modificação: Este ponto está relacionado ao anterior, nossa implementação antiga não nos obrigou a fazer nenhuma modificação, mas estendemos a implementação antiga para adicionar novos comportamentos, e quero dizer aqui usando a interface em vez disso de projeto para implementação.
- Prefira composição a herança: o decorador usa a composição aqui ao invés de tentar usar herança, em geral usar herança pode causar problemas por aumentar o acoplamento, e poderíamos discutir isso em um blog separado.
Anexe responsabilidades adicionais a um objeto dinamicamente. Os decoradores fornecem uma alternativa flexível à subclassificação para estender a funcionalidade.
Em nosso exemplo anexamos duas responsabilidades dinamicamente em tempo de execução, adicionamos o imposto ao preço e subtraímos o desconto do preço, não fizemos subclassificação para o DefaultPayment, usamos o poder do OOP para adicionar nossos comportamentos de maneira flexível, e esse é o padrão Decorator .





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)