Considere duas classes Dog
e Cat
ambas em conformidade com o Animal
protocolo (em termos da linguagem de programação Swift. Essa seria a interface em Java / C #).
Temos uma tela exibindo uma lista mista de cães e gatos. Há Interactor
classe que lida com a lógica nos bastidores.
Agora, queremos apresentar um alerta de confirmação ao usuário quando ele desejar excluir um gato. No entanto, os cães precisam ser excluídos imediatamente, sem nenhum alerta. O método com condicionais ficaria assim:
func tryToDeleteModel(model: Animal) {
if let model = model as? Cat {
tellSceneToShowConfirmationAlert()
} else if let model = model as? Dog {
deleteModel(model: model)
}
}
Como esse código pode ser refatorado? Obviamente cheira
fonte
Dog
eCat
são descritas como classes, enquanto queAnimal
é um protocolo que é implementado por cada uma dessas classes. Portanto, há um pouco de incompatibilidade entre a pergunta e sua resposta.Interactor
estado agoraCat
eDog
são tratados, ele pode e deve ser uma propriedade comum emAnimal
. Fazer qualquer outra coisa está pedindo dor de cabeça para manutenção mais tarde.Tell vs. Ask
A abordagem condicional que você está mostrando, chamaríamos de " perguntar ". É aqui que o cliente consumidor pergunta "de que tipo você é?" e personaliza seu comportamento e interação com os objetos de acordo.
Isso contrasta com a alternativa que chamamos de " contar ". Usando o tell , você envia mais do trabalho para as implementações polimórficas, para que o código do cliente consumidor seja mais simples, sem condicionais e comum, independentemente das implementações possíveis.
Como você deseja usar um alerta de confirmação, você pode tornar isso um recurso explícito da interface. Portanto, você pode ter um método booleano que, opcionalmente, verifica com o usuário e retorna a confirmação booleana. Nas classes que não desejam confirmar, elas simplesmente substituem
return true;
. Outras implementações podem determinar dinamicamente se desejam usar a confirmação.O cliente consumidor sempre usaria o método de confirmação, independentemente da subclasse específica com a qual trabalha, o que torna a interação informada em vez de perguntar .
(Outra abordagem seria empurrar a confirmação para a exclusão, mas isso surpreenderia os clientes consumidores que esperam que uma operação de exclusão seja bem-sucedida.)
fonte
Interactor
estado agoraDeterminar se uma confirmação é necessária é de responsabilidade da
Cat
classe, portanto, habilite-a para executar essa ação. Eu não conheço Kotlin, então vou expressar as coisas em c #. Espero que as idéias também sejam transferíveis para Kotlin.Em seguida, ao criar uma
Cat
instância, você a forneceráTellSceneToShowConfirmationAlert
, que precisará retornartrue
se OK para excluir:E então sua função se torna:
fonte
Cat
classe. Eu diria que é aí que ele pertence. Ele não decide como essa confirmação é alcançada (que é injetada) e não se exclui. Portanto, não, ela não move a lógica de exclusão para o modelo.TellSceneToShowConfirmationAlert
em uma instância doCat
. Em situações em que isso não é algo fácil (como em um sistema de várias camadas em que essa funcionalidade se encontra em um nível profundo), essa abordagem não seria boa.Eu recomendaria ir para um padrão de visitante. Eu fiz uma pequena implementação em Java. Não conheço o Swift, mas você pode adaptá-lo facilmente.
O visitante
Seu modelo
Ligar para o visitante
Você pode ter quantas implementações do AnimalVisitor quiser.
Exemplo:
fonte