O modo Decorador também é chamado de modo Wrapper.
1. A intenção é
adicionar dinamicamente algumas responsabilidades adicionais a um objeto.
2. Participantes
• Componente abstrato (Component): Define uma interface de objeto que pode adicionar dinamicamente responsabilidades a esses objetos.
• Componente Concreto: Defina um objeto e adicione algumas responsabilidades a este objeto.
• Decorador abstrato (Decorator): contém uma instância de um objeto componente e define uma interface consistente com a interface abstrata do componente .
• Decorador de Concreto: Adiciona responsabilidades aos componentes.
3. Estrutura
No padrão de design de Yan Hong, é mencionado que “o padrão de decoração estende a funcionalidade dos objetos de forma transparente ao cliente e é uma alternativa às relações de herança”.
Primeiro, vamos entender o propósito do modo de decoração – adicionar dinamicamente algumas responsabilidades adicionais a um objeto.
A chamada dinâmica significa que outras responsabilidades podem ser adicionadas dinamicamente ao objeto durante o tempo de execução do sistema (RunTime) sem a necessidade de modificar o código ou recompilar;
A chamada estática significa que o código (DesignTime) deve ser ajustado para adicionar responsabilidades ao objeto, e o sistema também precisa ser recompilado;
A partir de um nível técnico específico, a combinação e herança de objetos correspondem à dinâmica e estática anteriores
Deveríamos usar mais a composição de objetos para manter a escalabilidade do tempo de execução do sistema e usar herança o menos possível, porque a herança torna o programa rígido!
Isto é favorecer a composição em vez da herança.
Vamos entender a frase “O modo decoração estende a funcionalidade dos objetos de forma transparente ao cliente e é uma alternativa às relações de herança”.
Decorator é uma classe muito especial no padrão decorator. Ela não apenas herda de Component (relacionamento É A), mas também mantém uma referência à instância do Componente (relacionamento TEM A). De outra perspectiva, entre Decorator e Component, ambos Combinação dinâmica relacionamentos também têm relacionamentos de herança estática.
Por que foi projetado assim?
A vantagem da composição é que você pode adicionar responsabilidades aos objetos em tempo de execução. O Decorator possui um componente ( HAS A ), que é projetado para permitir que decoradores concretos (Concrete Decorator) adicionem dinamicamente responsabilidades a componentes concretos (Concrete Component) em tempo de execução . é relativamente É relativamente fácil de entender;
Então, qual é o propósito do Decorator herdar do Component?
Aqui a herança tem apenas um propósito, que é unificar as interfaces do decorador e do decorado.De outra perspectiva, seja um componente concreto (Concrete Component) ou um decorador concreto (Concrete Decorator) , ambos são Componentes. Usuários O código pode tratá-los como componentes. O benefício adicional disso é que a extensão das responsabilidades funcionais do objeto decorador para o objeto decorado é completamente transparente para o código do usuário , porque o código do usuário faz referência a todos. não haverá erros no código do usuário que se refere ao objeto decorado após ele ser decorado, na verdade não haverá impacto, pois antes e depois da decoração o código do usuário se refere a objetos do tipo Componente.
O padrão decorador unifica as interfaces do decorador e do objeto decorado por meio de herança e obtém a capacidade de estender dinamicamente o objeto decorado em tempo de execução por meio de composição .
Vamos ilustrar com um exemplo:
Primeiro, em vez de usar o modo decoração, pense em como atender aos seguintes requisitos.
1. Tomemos como exemplo a compra de um carro - os clientes vão a uma concessionária para comprar um carro, e o agente presta alguns serviços, inicialmente alguns serviços de manutenção pós-venda;
2. Posteriormente, prestou também serviços de fornecimento de peças, depois prestou alguns serviços de consultoria (os agentes responderam a algumas dúvidas que os clientes tinham antes de comprar um carro) e, por fim, prestou serviços de seguro automóvel aos clientes.
3. Se o agente necessita fornecer diferentes combinações de serviços de acordo com a situação.
(Não vou escrever código para implementá-lo aqui)
Na maioria dos casos, é utilizada herança, o que causa principalmente os seguintes problemas:
1. O sistema tem baixa escalabilidade;
2. Quando diferentes combinações de serviços precisam ser fornecidas, um grande número de classes precisa ser criado, causando explosão de classes;
Então, vamos ver como o modo de decoração atende aos requisitos acima. O código Java é o seguinte:
Componente Resumo: Revendedor de automóveis
/**
* 抽象构件(Component)
*
* 汽车销售商
*/
public interface CarSeller {
/*
* 销售汽车
*/
String sellCars();
}
Componente de concreto: concessionária Audi
/**
* 具体构件(Concrete Component)
*
* 奥迪汽车经销商
*/
public class AudiCarAgency implements CarSeller {
/*
* 销售奥迪汽车
*/
public String sellCars() {
System.out.println("销售奥迪汽车");
return "奥迪汽车";
}
}
Decorador: concessionário Audi oferecendo serviços
/**
* 抽象装饰者(Decorator)
*
* 提供服务的奥迪销售商
*/
public class AudiCarAgencyWithServices implements CarSeller {
private CarSeller carSeller = null;
/*
* 构造函数
*/
public AudiCarAgencyWithServices(CarSeller carSeller) {
this.carSeller = carSeller;
}
/*
* 装饰
* @see myDecoratorPattern.sellCars.CarSeller#sellCars()
*/
public String sellCars() {
String carName = null;
carName = carSeller.sellCars();
return carName;
}
}
Decorador de concreto: concessionário Audi que presta serviços de reparo
/**
* 具体装饰者(Concrete Decorator)
*
* 提供维修服务的奥迪销售商
*
*/
public class AudiCarAgencyWithMaintenance extends AudiCarAgencyWithServices {
/*
* 构造函数
*/
public AudiCarAgencyWithMaintenance(CarSeller carSeller) {
super(carSeller);
}
/*
* 添加了其他的服务
*/
public String sellCars(){
String carName = super.sellCars();
System.out.println("提供维修服务");
return carName;
}
}
Decorador de concreto: revendedor Audi fornece fornecimento de peças de reposição
/**
* 具体装饰者(Concrete Decorator)
*
* 提供零配件供应的奥迪销售商
*
*/
public class AudiCarAgencyWithSparepart extends AudiCarAgencyWithServices {
/*
* 构造函数
*/
public AudiCarAgencyWithSparepart(CarSeller carSeller) {
super(carSeller);
}
/*
* 添加了其他的服务
*/
public String sellCars(){
String carName = super.sellCars();
System.out.println("提供零配件供应");
return carName;
}
}
Decorador de concreto: concessionário Audi que presta serviços de consultoria pré-venda
/**
* 具体装饰者(Concrete Decorator)
*
* 提供售前咨询服务的奥迪销售商
*
*/
public class AudiCarAgencyWithConsultation extends AudiCarAgencyWithServices {
/*
* 构造函数
*/
public AudiCarAgencyWithConsultation(CarSeller carSeller){
super(carSeller);
}
/*
* 添加了其他的服务
*/
public String sellCars() {
System.out.println("提供了售前咨询服务");
return super.sellCars();
}
}
Decorador de concreto: revendedor Audi que oferece serviços de seguros de automóveis
/**
* 具体装饰者(Concrete Decorator)
*
* 提供车险服务的奥迪销售商
*
*/
public class AudiCarAgencyWithInsurance extends AudiCarAgencyWithServices {
/*
* 构造函数
*/
public AudiCarAgencyWithInsurance(CarSeller carSeller) {
super(carSeller);
}
/*
* 添加了其他的服务
*/
public String sellCars(){
String carName = super.sellCars();
System.out.println("提供车险的购买");
return carName;
}
}
A estrutura é a seguinte:
Chamada do cliente:
public class Customer {
public static void main(String[] args){
String car = null;
System.out.println("--------------只卖车,没有服务------------------");
// 汽车经销商
CarSeller carSeller = new AudiCarAgency();
car = carSeller.sellCars();
System.out.println("买到了" + car);
System.out.println("--------------第一种组合-维修服务------------------");
// 提供了维修服务
CarSeller carSellerWithMaintenance = new AudiCarAgencyWithMaintenance(carSeller);
car = carSellerWithMaintenance.sellCars();
System.out.println("买到了" + car);
System.out.println("--------------第二种组合-添加了零部件供应服务---------");
// 提供了零部件供应
CarSeller carSellerWithSparepart = new AudiCarAgencyWithSparepart(carSellerWithMaintenance);
car = carSellerWithSparepart.sellCars();
System.out.println("买到了" + car);
System.out.println("--------------第三种组合-添加了咨询服务--------------");
// 提供了咨询服务
CarSeller carSellerWithConsultation = new AudiCarAgencyWithConsultation(carSellerWithSparepart);
car = carSellerWithConsultation.sellCars();
System.out.println("买到了" + car);
System.out.println("--------------第四种组合-添加了车险服务--------------");
// 提供了车险
CarSeller carSellerWithInsurance = new AudiCarAgencyWithInsurance(carSellerWithConsultation);
car = carSellerWithInsurance.sellCars();
System.out.println("买到了" + car);
System.out.println("#########################################");
// 还可以有其他的组合方式
System.out.println("还可以尝试其他形式自由的组合。。。。。。");
}
}
resultado da operação:
--------------只卖车,没有服务------------------
销售奥迪汽车
买到了奥迪汽车
--------------第一种组合-维修服务------------------
销售奥迪汽车
提供维修服务
买到了奥迪汽车
--------------第二种组合-添加了零部件供应服务---------
销售奥迪汽车
提供维修服务
提供零配件供应
买到了奥迪汽车
--------------第三种组合-添加了咨询服务--------------
提供了售前咨询服务
销售奥迪汽车
提供维修服务
提供零配件供应
买到了奥迪汽车
--------------第四种组合-添加了车险服务--------------
提供了售前咨询服务
销售奥迪汽车
提供维修服务
提供零配件供应
提供车险的购买
买到了奥迪汽车
#########################################
还可以尝试其他形式自由的组合。。。。。。
Você pode ver que usar o modo decoração tem as seguintes vantagens:
1. O objetivo do modo de decoração e do relacionamento de herança é estender a funcionalidade dos objetos, mas o modo de decoração pode fornecer mais flexibilidade do que a herança.
2. Ao usar diferentes classes de decoração específicas e as permutações e combinações dessas classes de decoração, os designers podem usar muito poucas classes para criar muitas combinações de comportamento diferentes.
O conteúdo acima é parcialmente referenciado em "Java and Patterns" de Yan Hong e detalhes de aplicação de exemplo de padrão de xícara de café-Decorator (Decorator)
Se você observar atentamente a invocação do modo decoração (por exemplo: a segunda combinação - adicionar um serviço de fornecimento de peças ), parece que o modo decoração e o modo proxy têm o mesmo efeito (ambos adicionam funções adicionais a um objeto); até mesmo , se comparados Parece não haver diferença na estrutura desses dois modos. Então, qual é a diferença entre eles?
Primeiro, suas intenções são diferentes:
O padrão proxy controla o acesso a um objeto.
O modo de decoração consiste em adicionar responsabilidades (funções) a uma classe.
A julgar apenas pela sua estrutura,
Ao usar o modo proxy, você também pode adicionar algumas operações adicionais antes ou depois de acessar o objeto. Nesse sentido, o modo de decoração é semelhante ao modo proxy. Pode-se até dizer que os dois modos são iguais, ambos adicionando uma classe (um objeto) outras funções.
Mas se você entender cuidadosamente as duas palavras “controlar” e “aumentar”, poderá descobrir que
No modo proxy, operações adicionais são frequentemente adicionadas para determinar se o objeto acessado pode ser acessado.
No modo decoração, essas funções adicionadas não afetarão o funcionamento dos objetos originais, e os objetos decorados serão definitivamente acessados.