È più facile da spiegare con un breve esempio. È anche meglio se Presenter e Conttroller sono separati come nella spiegazione dello zio Bos. È comunque necessario se si desidera implementare Dependency Injection con un contenitore IoC.
Supponiamo che tu abbia un semplice caso d'uso in cui l'utente può cercare un cliente dall'ID e visualizzarne il nome, oppure un messaggio di errore se il client non viene trovato.
La classe View ha un Controller e un Presenter nel suo costruttore.
Ha un TextBox per l'ID da cercare e un pulsante per avviare la ricerca.
Ha anche 2 TextBlocks per il nome del cliente e il messaggio di errore. Questi 2 sono associati alle proprietà nel Presenter.
Quando l'utente fa clic sul pulsante, la vista ottiene il contenuto TextBox e chiama controller.Search(id)
.
In definitiva, UseCaseInteractor
controlla completamente il comportamento, sia che scelga di visualizzare il client o un messaggio di errore (o qualsiasi altra cosa ...).
Alcuni pseudo-codice per C #:
class Controller {
Controller(IUseCaseInput){ }
Search(clientId){ input.Search(clientId); }
}
interface IUseCaseInput { Search(clientId); }
class UseCaseInteractor : IUseCaseInput {
UseCaseInteractor(IUseCaseOutput) { }
Search(clientId){
client = ...
if (client == null) {
output.SetError("Argh!.";
} else {
output.SetClient(client);
}
}
}
interface IUseCaseOutput {
SetError(message);
SetClient(client);
}
class Presenter : IUseCaseOutput {
string Error { get; set; }
string Name { get; set }
SetError(message) { Error = message; }
SetClient(client) { Name = client.Name; }
}
Non molto naturale quando si è abituati a MVVM, ma fa perfettamente il lavoro per rinviare tutte le decisioni al caso d'uso. Assomiglia molto più a ciò che fa un framework MVC per il Web.