Padrão de delegado

O padrão delegado é um dos principais padrões de design.
Digamos que estamos desenvolvendo um aplicativo para uma barbearia. O aplicativo possui um calendário para seleção de um dia para gravação; ao tocar na data deverá abrir uma lista de barbeiros com opção.
Vamos implementar uma ligação ingênua de componentes do sistema, combinar o calendário e a tela usando ponteiros entre si para implementar uma exibição de lista:


// псевдокод

class BarbershopScreen {
   let calendar: Calendar

   func showBarbersList(date: Date) {
      showSelectionSheet(barbers(forDate: date))
   }
}

class Calendar {
    let screen: BarbershopScreen

    func handleTap(on date: Date) {
        screen.showBarbersList(date: date)
    }
}

Depois de alguns dias, os requisitos mudam; antes de exibir a lista, é necessário mostrar ofertas com opção de serviços (aparar barba, etc.), mas nem sempre, em todos os dias, exceto sábado.
Adicionamos ao calendário uma verificação se é sábado ou não, dependendo disso chamamos o método da lista de barbeiros ou da lista de serviços, para maior clareza irei demonstrar:


// псевдокод

class BarbershopScreen {
   let calendar: Calendar

   func showBarbersList(date: Date) {
      showSelectionSheet(barbers(forDate: date))
   }

   func showOffersList() {
      showSelectionSheet(offers)
   }
}

class Calendar {
    let screen: BarbershopScreen

    func handleTap(on date: Date)  {
        if date.day != .saturday {
             screen.showOffersList()
        }
        else {
             screen.showBarbersList(date: date)
        }
    }
}

Uma semana depois, somos solicitados a adicionar um calendário à tela de feedback e, nesse momento, acontece o primeiro erro arquitetônico!
O que fazer? O calendário está intimamente ligado à tela de marcação de corte de cabelo.
uau! eca! ah ah
Se você continuar trabalhando com essa arquitetura maluca de aplicação, você deve fazer uma cópia de toda a classe de calendário e associar essa cópia à tela de feedback.
Ok, parece bom, então adicionamos mais algumas telas e várias cópias do calendário, e então chegou o momento X. Fomos solicitados a alterar o design do calendário, o que significa que agora precisamos encontrar todas as cópias do calendário e adicionar as mesmas alterações a todas. Essa “abordagem” afeta muito a velocidade de desenvolvimento e aumenta a chance de cometer erros. Como resultado, tais projetos acabam em um estado quebrado, quando até mesmo o autor da arquitetura original não entende mais como funcionam as cópias de suas aulas, e outros hacks adicionados ao longo do caminho desmoronam na hora.
O que precisava ser feito, ou melhor ainda, o que não era tarde demais para começar a fazer? Use o padrão de delegação!
A delegação é uma forma de passar eventos de classe por meio de uma interface comum. Abaixo está um exemplo de delegado para um calendário:

protocol CalendarDelegate {
   func calendar(_ calendar: Calendar, didSelect date: Date)
}

Agora vamos adicionar o código para trabalhar com o delegado ao código de exemplo:


// псевдокод

class BarbershopScreen: CalendarDelegate {
   let calendar: Calendar

   init() {
       calendar.delegate = self
   }

   func calendar(_ calendar: Calendar, didSelect date: Date) {
        if date.day != .saturday {
            showOffersList()
        }
        else {
             showBarbersList(date: date)
        }
   }

   func showBarbersList(date: Date) {
      showSelectionSheet(barbers(forDate: date))
   }

   func showOffersList() {
      showSelectionSheet(offers)
   }
}

class Calendar {
    weak var delegate: CalendarDelegate

    func handleTap(on date: Date)  {
        delegate?.calendar(self, didSelect: date)
    }
}

Como resultado, desvinculamos completamente o calendário da tela ao selecionar uma data no calendário, ele transmite o evento de seleção de data – *delega* processamento de eventos ao assinante; O assinante é a tela.
Que benefícios obtemos com esta abordagem? Agora podemos alterar a lógica do calendário e da tela de forma independente, sem duplicar classes, simplificando ainda mais o suporte; Desta forma, é implementado o “princípio da responsabilidade exclusiva” pela implementação dos componentes do sistema e observado o princípio DRY.
Ao usar a delegação, você pode adicionar, alterar a lógica de exibição das janelas, a ordem de qualquer coisa na tela, e isso não afetará em nada o calendário e outras classes, que objetivamente não devem participar de processos não diretamente relacionados a elas.< br/>Alternativamente, os programadores que não se preocupam muito usam o envio de mensagens através de um barramento comum, sem escrever uma interface separada de protocolo/delegado, onde seria melhor usar a delegação. Escrevi sobre as desvantagens dessa abordagem em um post anterior & # 8211; “Padrão do Observador.”

Fontes

https://refactoring.guru/ru/replace-inheritance -com delegação