Definição: permite que vários objetos tenham a oportunidade de processar a solicitação, evitando assim a relação de acoplamento entre o remetente e o receptor da solicitação. Conecte esses objetos a uma corrente e passe a solicitação ao longo da cadeia até que um objeto a processe.
Tipo: padrão comportamental
Diagrama de classe:
Vamos primeiro olhar para um pedaço de código:
Teste public void (int i, solicitação de solicitação) {if (i == 1) {Handler1.Response (request); } else if (i == 2) {handler2.Response (request); } else if (i == 3) {Handler3.Response (solicitação); } else if (i == 4) {handler4.Response (request); } else {Handler5.Response (request); }} A lógica de negócios do código é a seguinte: o método possui dois parâmetros: o número inteiro i e uma solicitação de solicitação. De acordo com o valor de I, que lidará com a solicitação, se eu == 1, ele será tratado pelo Handler1, se eu == 2, ele será tratado pelo Handler2 e assim por diante. Na programação, esse tipo de método de processamento de negócios é muito comum. Todas as classes que processam solicitações incluem se ... else ... declarações de julgamento condicional conectadas a uma cadeia de responsabilidade de processar a solicitação. Eu acredito que todo mundo costuma usar. As vantagens desse método são que ele é muito intuitivo, simples e claro e relativamente fácil de manter, mas esse método também tem várias dores de cabeça:
Código inchado: em aplicativos reais, as condições de julgamento geralmente não são tão simples para determinar se são 1 ou 2. Pode exigir cálculos complexos, talvez consultando o banco de dados, etc. Isso terá muito código extra. Se houver muitas condições de julgamento, essa afirmação se ... else ... é basicamente impossível de ler.
Alto grau de acoplamento: se quisermos continuar adicionando classes que processam solicitações, devemos continuar adicionando mais se as condições do julgamento; Além disso, a ordem dessa condição também é escrita para os mortos. Se quisermos alterar o pedido, só podemos modificar esta instrução de condição.
Como já entendemos as deficiências, precisamos encontrar uma maneira de resolvê -las. A lógica de negócios desse cenário é muito simples: se a condição 1 for atendida, será processada pelo Handler1 e, se não for atendida, será transmitida; Se a condição 2 for atendida, será processada pelo Handler2 e, se não for atendida, será transmitida e assim por diante até o final da condição. De fato, o método de melhoria também é muito simples, que é colocar a parte das condições de julgamento na classe de processamento. Este é o princípio do modelo de conexão de responsabilidade.
A estrutura do modelo da empresa de responsabilidade
O diagrama de classes do padrão conectado à responsabilidade é muito simples, consiste em uma classe abstrata processada e seu conjunto de classes de implementação:
Classe de processamento abstrato: A classe de processamento abstrata inclui principalmente uma variável de membro Nexthandler apontando para a próxima classe de processamento e uma solicitação de mão de método que lida com a solicitação. A principal idéia do método Handrequest é que, se as condições de processamento forem atendidas, essa classe de processamento será processada, caso contrário, será processada pelo Nexthandler.
Classe de processamento específica: a classe de processamento específica implementa principalmente a lógica de processamento específica e as condições aplicáveis para o processamento.
Exemplo
A cadeia de Modelo de Responsabilidade tem duas funções:
Função do manipulador abstrato: define uma interface solicitada. Se necessário, você pode definir um método para definir e retornar a referência ao próximo objeto doméstico.
Função de concreto para manipulação: se puder ser processado, processe a solicitação. Se não puder ser processado, passe a solicitação para a próxima casa e deixe a próxima casa lidar com ela. Ou seja, ele lida com solicitações que pode lidar e pode acessar sua próxima casa.
O código de teste para o padrão acima é o seguinte:
Pacote ChainOfResp;/***Descrição: Role do processamento abstrato*/Public Abstract Class Handler {Sucessor de manipulador protegido; / ***Descrição: Método de Processamento*/ Public Resumo Void HandlerRequest (condição da String); manipulador público getsuccessor () {return sucessor; } public void SetSuccessor (sucessor Handler) {this.successor = sucessor; }} pacote cadeiafrep;/***Descrição: manuseio detalhado de funções*/public class concreteHandler1 estende o manipulador {@Override public void HandlerRequest (condição da string) {// Se for sua própria responsabilidade, você o lidará e será responsável por passá -lo para a próxima casa se (condicional. retornar ; } else {System.out.println ("concretehandler1 passou"); getSuccessor (). HandlerRequest (condição); }}} pacote cadeiafresp;/***Descrição: manuseio detalhado de funções*/public class concreteHandler2 estende o manipulador {@Override public void HandlerRequest (condição da string) {// Se for sua própria responsabilidade, você o lidará com ele mesmo e será responsável por passá -lo para a próxima casa se (condicional.Int.Equals ("concretHandler2"). retornar ; } else {System.out.println ("concretehandler2 passou"); getSuccessor (). HandlerRequest (condição); }}} Pacote ChainOfresp;/*** Descrição: Função detalhada do processamento*/Classe pública ConcreteHandlern estende o manipulador {/*** Aqui é assumido que n é o último nó da cadeia que deve ser processado* em situações reais, um anel ou uma árvore pode parecer:* Este não é necessariamente o último nó. * */ @Override public void HandlerRequest (condição da String) {System.out.println ("ConcreteHandlern Manused"); }} pacote cadeiafresp;/***Descrição: classe de teste*/public class Client {/***Descrição:*/public static void main (String [] args) {manipulador de manipulador1 = new concreteHandler1 (); Handler Handler2 = novo concretoHandler2 (); Manipulador handlern = new concreteHandlern (); // Chain Handler1.SetSuccessor (Handler2); Handler2.SetSUccessor (Handlern); // Suponha que essa solicitação seja de responsabilidade do concretoHandler2 Handler1.HandlerRequest ("ConcreteHandler2"); }}
Para dar este exemplo, na oficina de produção de uma fábrica de brinquedos, a linha de montagem é uma cadeia de responsabilidade. Se uma aeronave de brinquedo possui um assembler de conchas, montador de motores, montador de hélice e empacotador de modelos. Quando a aeronave flui para quem quer que o objeto esteja fluindo, ele será responsável por instalar a parte pela qual é responsável. Depois que esta parte for instalada, ela fluirá para a próxima etapa e saberá que todos os ambientes são concluídos. Esta é uma cadeia de responsabilidade gerada. Há também uma cadeia de inspeção de qualidade, dividida em várias partes, inspeção de conchas, inspeção do motor, inspeção de hélice e inspeção de embalagens. Quando o produto é deixado ao inspetor para testar a peça pela qual ele é responsável, se houver algum problema, será retirado diretamente. Se não houver problema, ele será passado para o próximo inspetor até que todos os testes sejam concluídos. Essas duas são cadeias de responsabilidade, mas a diferença é que todos processarão a cadeia de responsabilidade e processarão parte dela; Após o julgamento, a cadeia de responsabilidade pela inspeção da qualidade será processada ou não processada. Estas são as duas categorias de cadeias de responsabilidade. O último é chamado de pura cadeias de responsabilidade, e o primeiro é chamado de impura cadeias de responsabilidade. As cadeias de responsabilidade pura raramente existem em aplicações práticas. O comum é as cadeias de responsabilidade impura. O modelo acima simula as cadeias de responsabilidade pura a serem manuseadas.
Prós e contras do modelo de cadeia de responsabilidade
Comparado com se ... else ..., o padrão da cadeia de responsabilidade tem uma capacidade de acoplamento mais baixa, pois distribui os julgamentos condicionais em várias classes de processamento, e a ordem de processamento prioritária dessas classes de processamento pode ser definida à vontade. O modelo da cadeia de responsabilidade também tem suas desvantagens, que é a mesma que a declaração se ... else ... ou seja, antes de encontrar a classe de processamento correta, todas as condições de julgamento devem ser executadas. Quando a cadeia de responsabilidade é relativamente longa, o problema de desempenho é mais grave.
Cenários aplicáveis para a cadeia de Modelo de Responsabilidade
Assim como o exemplo inicial, se você se sentir sobrecarregado ao usar a declaração If ... else ... para organizar uma cadeia de responsabilidade e o código parece ruim, você pode usar a cadeia do modo de responsabilidade para refatorá -la.
Resumir
O modelo de cadeia de responsabilidade é na verdade uma versão flexível de If ... else ... declaração. Ele coloca essas condições de julgamento em cada classe de processamento. A vantagem disso é que é mais flexível, mas também traz riscos. Por exemplo, ao configurar o relacionamento entre a classe de processamento antes e depois da aula de processamento, você deve ter muito cuidado para julgar a relação entre a lógica condicional antes e depois da classe de processamento e ter cuidado para não ter referências circulares na cadeia.