Padrões de design: comando e conserje na vida e Ruby

A definição do Padrão de Comando é estressante a ser observada. A definição formal é que:

  • encapsula um pedido como objeto
  • permitindo que você parametralize outros objetos com solicitações diferentes, solicitações de fila ou de logs e suporte a operações desfazíveis.

Vamos esquecer por um segundo e fazer uma viagem ao Havaí.

E viva em um hotel de luxo.

Passamos o dia na praia, mergulhamos e fizemos um passeio. É hora de voltar para o hotel para relaxar, comer e planejar para o próximo dia.

Depois de voltar para o hotel, queremos:

  1. Obter serviço de quarto para jantar
  2. Obter serviço de lavanderia porque não trouxemos roupas extras
  3. Obter um guia de viagem para Kauai, a ilha que vamos para o amanhã

Verificamos o menu de serviço do hotel e encontramos três itens de serviço que atendem às nossas necessidades.

Em seguida, chamamos a recepção para colocar esses três pedidos. Um concierge pega nossa ligação, escreve nossa lista de solicitações e atua em cada solicitação de serviço conforme instruído pelo menu de serviço.

Em seguida, cada membro da equipe executa de acordo com cada solicitação específica:

  1. O cozinheiro chefe na cozinha começa a cozinhar
  2. O departamento de limpeza envia uma equipe para o nosso quarto para pegar nossas roupas
  3. A equipe do lobby agarra um guia de viagem e entrega-o ao nosso quarto

Vamos recapitular o que aconteceu.

uma. Nós selecionamos os serviços que queríamos no menu e os enviamos para um concierge.

b. O concierge escreveu esses pedidos de serviço como uma lista.

c. Depois de desligarmos, instruídos pelo menu de serviço, o concierge enviou nossos pedidos aos departamentos correspondentes.

d. Cada departamento executado no pedido solicitado.

Vamos ver as ações em Ruby.

1. Enviamos esses três pedidos para o concierge:

2. Estes pedidos entraram em uma lista que o porteiro acompanhava:

Vamos ver isso em ação (console):

Como podemos ver, depois we apresentou três pedidos, estes pedidos estavam em um request_list cuidar de concierge .

3. Instruido pelo menu de serviço, o concierge enviou nossos pedidos aos departamentos correspondentes.

O código acima deve funcionar bem.

Exceto por uma coisa….

Cheira mal.

Especificamente, a parte em que temos os casos de troca:

Por que esta parte cheira mal?

  1. Se o hotel oferece vinte serviços, em vez de três, o método será muito longo.
  2. Queremos oferecer novos serviços ou remover um serviço existente. No entanto, cada vez que temos que abrir a classe Concierge e redefinir o método act_on_requests .

O método sabe demais e requer mudanças frequentes . Ter essas duas combinações juntas é quase sempre uma coisa ruim.

Por quê?

Um método que requer mudanças freqüentes é um método que você precisa atualizar com freqüência. Cada vez que você atualiza um código é uma oportunidade para introduzir novos insetos no sistema.

Quando o método também conhece uma tonelada – e é longo – as chances de estragar isso quando a atualização aumentar significativamente. Esse é o raciocínio por trás de um princípio de design sobre o qual conversamos anteriormenteencapsular o que varia.

Tempo para Refactor!

Deve haver uma maneira melhor do que isso:

Veja mais de perto e pense nisso.

Vamos reformular o que o código está fazendo em inglês. Fazemos o percurso nos pedidos na lista de pedidos. Para cada solicitação, de acordo com seu tipo de serviço, fornecemos os correspondentes dados relacionados ao departamento e executamos o pedido. Essencialmente, nós seguimos os pedidos e executamos cada um deles de acordo.

Mas e se cada pedido realmente soubesse como se executar?

Então o método pode ser tão simples como:

Em vez de deixar o método act_on_requests decidir como cada pedido deve ser tratado, distribuímos essa responsabilidade e conhecimento de volta a cada solicitação e deixamos que ele decida como deve ser tratado.

Com isso dito, nossos pedidos podem ser assim:

E o Concierge atualizado será:

Com os códigos atualizados, aqui é como nós, clientes do hotel, enviamos pedidos ao concierge.

É muito fácil criar outro serviço.

Por exemplo, o hotel também nos permite reservar SPA:

O serviço não só suporta a execute (fazendo uma reserva de spa), mas também undo (cancelar a reserva).

Digamos que o hotel também oferece outra maneira de solicitar serviços sem ter que ligar para o concierge – um painel de solicitação de serviço:

Podemos simplesmente pressionar o botão e o serviço com uma configuração padrão será entregue à nossa sala.

Aqui está o código para o ServicePanel :

E aqui é como podemos criar um painel de serviço:

??Estamos agora usando o padrão de comando! ??

Vamos rever a definição do padrão de comando. Isto:

  • encapsula um pedido como objeto
  • permitindo que você parametralize outros objetos com solicitações diferentes, solicitações de fila ou de logs e suporte a operações desfazíveis.

1. "encapsula uma solicitação como objeto"

Cada uma das classes de serviços que criamos, RoomService , LaundryService , TripPlanningService e SpaReservationService , é um exemplo de encapsular uma solicitação como objeto.

Recapitular:

2. ", permitindo-lhe parametrizar outros objetos com solicitações diferentes"

O ServicePanel é um exemplo de parametrização de um objeto com solicitações diferentes.

Recapitular:

3. "solicitações de fila ou log",

Nossos pedidos foram enfileirados enquanto o porteiro os levava por telefone.

Recapitular:

4. e suporta operações desfazíveis.

SpaReservationService suporta undo .

Recapitular:

Obrigado por ler!

Não se esqueça de se inscrever. : D

Isto foi originalmente publicado no meu blog, padrões de design na vida e Ruby .

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *