2012-09-17 18 views
6

Come noto nell'implementazione standard di MVC passiamo Controller e Modello alla vistaMVC: devo utilizzare Controller nella vista?

Ma sono un po 'in disaccordo con questa idea. Non voglio che la mia vista sia a conoscenza del controller e del modello (oh no forse a volte la vista ha bisogno del modello, ma sono sicuro che può vivere senza conoscenza del controller)

A mio parere Controller dovrebbe gestire Vista e Modello, e Model non ha bisogno di sapere su controller e view; la vista non ha bisogno di conoscere il controller (non escludo il modello perché alcune implementazioni di viste devono conoscere il modello per ascoltare i cambiamenti nel modello). Quindi la mia idea è che la vista non debba conoscere il controller.

1. Ecco un esempio:

public class MyView implements ButtonClickListener { 

    private Controller myController; 
    private Button myButton; 

    // I commented out the model because we dont need it now 
    // we are talking about using controller in the view 

    public MyView(Controller c/*, Model m*/) { 
     myController = c; 
     myButton  = new Button(); // lets say that it is "register" button 
     myButton.setOnButtonClickListener(this); 
    } 

    public void setRegisterButtonText(String text) { 
     myButton.setText(text); 
    } 

    @Override 
    public void onClick() { 
     myController.tellToModelToDoSomething(); 
    } 

} 

e regolatore:

public MyController implements Controller { 

    private Model model; 
    private View view; 

    public MyController(Model model) { 

      this.model = model; 
      this.view = new MyView(this); 

    } 

    public void tellToModelToDoSomething() { 
      model.doSomeActions(); 
    } 


} 

2. E ora come faccio a vedere questa implementazione, senza passare il controllore:

La mia vista:

public class MyView { 

    private Button myButton; 

    public MyView() { 
     myButton = new Button(); 
    } 

    public void setRegisterButtonText(String text) { 
     myButton.setText(text); 
    } 

    public void setOnRegisterButtonClick(final Command command) { 
     myButton.setOnButtonClickListener(new ButtonClickListener() { 
          @Override 
          public void onClick() { 
           command.execute(); 
          } 
         }); 
    } 

} 

interfaccia "Command":

public interface Command { 

    void execute(/*also can handle extra params*/); 

} 

e regolatore:

public MyController implements Controller { 

private Model model; 
private View view; 

public MyController(Model model) { 

     this.model = model; 
     this.view = new MyView(); 

     view.setOnRegisterButtonClick(command); 

} 

public void tellToModelToDoSomething() { 
     model.doSomeActions(); 
} 

private Command command = new Command() { 

    public void execute() { 
      tellToModelToDoSomething(); 
    } 

}; 

}

Allora, perché penso che l'utilizzo del controller nella vista NON FA BENE:

Stiamo mixando controller e visualizzare le implementazioni, creando nuove dipendenze.

Inoltre, penso che la vista dovrebbe contenere solo VISTE e operazioni con essi (e usare il controller e alcuni dei suoi metodi già sembra logica).

Nella prima vista di esempio indica al controller cosa fare. Sei d'accordo? Sembra che la vista controlli il controller!

Nel secondo controller esempio controlla cosa fare e dice solo alla vista che cosa fare se qualche pulsante (solo vista sa cosa tasto sarà) cliccato

ho sempre usato il secondo schema, ma dopo aver letto un nuovo libro su mvc, che dice che dobbiamo passare il controller alla vista, sono un po 'confuso.

Potete per favore aiutarmi a capire perché mi sbaglio e mostrarmi qualche esempio?

+0

Credo che controller e vista non interagiscano direttamente. Interagiscono anche se il modello. così il modello conosce sia il controller che la vista ma la vista e il controller non si conoscono. – gigadot

+2

detto questo. MVC è disponibile in molte varianti e le reali implmenti sono diverse nella pratica. – gigadot

+0

hai ragione .. e come pensi in questo esempio, quale implementazione è migliore? – pleerock

risposta

11

Non esiste uno standard MVC, in quanto vi sono molte implementazioni. Ecco un'interpretazione di MVC che viene insegnata in molti libri di testo:

La definizione del controller in questa interpretazione è che gestisce gli eventi dalla vista, quindi la vista deve utilizzare il controller.

In MVC standard, il modello contiene ed espone i dati, il controllore manipola il modello e accetta eventi dalla vista e la vista presenta il modello e genera eventi per il controller.

MVC è considerato un sistema transazionale, in cui una transazione viene avviata da un evento. Le transazioni si presentano in genere in questo modo:

  1. Un evento (come un clic del pulsante) viene generato sulla vista.
  2. Le informazioni sull'evento vengono passate dalla vista al controller.
  3. Il controllore chiama i metodi sul modello per modificarlo (setter e altri metodi di manipolazione che possono aggiornare alcuni database).

Questi primi passi rappresentano il collegamento V-C e il collegamento M-C. V-C esiste perché gli eventi vengono passati dalla vista al controller per essere elaborati invece della vista che li gestisce direttamente. Il collegamento M-C esiste perché il modello viene aggiornato dal controllore in base all'evento che è stato attivato.

Da qui, ci sono due percorsi. Il primo:

  1. La transazione termina.
  2. Separatamente, il modello genera i propri eventi per indicare che è stato modificato.
  3. La vista sta ascoltando il modello e riceve l'evento e aggiorna la rappresentazione del modello per riflettere le modifiche.

Questo primo percorso rappresenta un'interpretazione del collegamento M-V. Il collegamento M-V è 1) la vista che riceve informazioni dal modello per i suoi dati e 2) il modello che indica la vista da aggiornare poiché è stata modificata.

Il secondo percorso è solo un passaggio: una volta che il controller ha elaborato l'evento, la vista si aggiorna immediatamente semplicemente aggiornando tutti gli elementi dell'interfaccia utente. Questa interpretazione del collegamento M-V è che il modello fornisce semplicemente la sua informazione alla vista, lo stesso del punto # 1 dal collegamento M-V nel primo percorso sopra.

Ecco alcuni del codice modificato per l'architettura MVC che ho descritto:

public class MyView implements View, ModelListener { 

    private Button myButton; 
    private Controller controller; 

    public MyView(Controller controller, Model model) { 
     myButton = new Button(); 
     myButton.setOnButtonClickListener(new ButtonClickListener() { 
      @Override 
      public void onClick() { 
       controller.onRegisterButtonClick(); 
      } 
     }); 
     this.controller = controller; 
     model.addModelListener(this); 
    } 

    public void setRegisterButtonText(String text) { 
     myButton.setText(text); 
    } 

    public void modelUpdated(Model model) { 
     // Update view from model 
    } 
} 

E il controllore:

public MyController implements Controller { 

    private Model model; 
    private View view; 

    public MyController(Model model) { 
     this.model = model; 
     this.view = new MyView(this, model); 
    } 

    private void manipulateModel() { 
     model.doSomeActions(); 
    } 

    public void onRegisterButtonClick() { 
     maniuplateModel(); 
    } 
} 

Poi il modello:

public class MyModel implements Model { 
    private List<ModelListener> modelListeners = new ArrayList<ModelListener>(); 

    public void addModelListener(ModelListener ml) { 
     if (!modelListeners.contains(ml)) { 
      modelListeners.add(ml); 
     } 
    } 

    public void removeModelListener(ModelListener ml) { 
     modelListeners.remove(ml); 
    } 

    public void doSomeActions() { 
     // Do something 
     fireUpdate(); 
    } 

    private void fireUpdate() { 
     // Iterates backwards with indices in case listeners want to remove themselves 
     for (int i = modelListeners.size() - 1; i >= 0; i-- { 
      modelListener.modelUpdated(this); 
     } 
    } 
} 

ModelListener è piuttosto semplice:

public interface ModelListener { 
    void modelUpdated(Model model); 
} 

Questa è solo una interpretazione. Se desideri un ulteriore disaccoppiamento tra le diverse parti, dovresti esaminare lo Presentation, Abstraction, Control (PAC) pattern. È più disaccoppiato di MVC ed è ottimo anche per i sistemi distribuiti. È eccessivo per applicazioni web, mobili e desktop semplici, ma alcune applicazioni client/server e la maggior parte delle applicazioni cloud possono trarre vantaggio da questo approccio.

In PAC, si dispone di tre parti, presentazione, astrazione e controllo, ma l'astrazione e la presentazione (il modello e la vista) non interagiscono tra loro.Invece, le informazioni passano solo dentro e fuori dal modulo di controllo. Inoltre, è possibile avere più sotto-moduli PAC che interagiscono tra loro solo attraverso i loro controlli, prestandosi a un buon modello per i sistemi distribuiti. Fondamentalmente, il modulo di controllo è l'hub principale di qualsiasi trasferimento di dati.

In sostanza, la tua interpretazione di MVC può essere diversa dalla mia o dalla loro. Ciò che conta è scegliere un modello architettonico e seguirlo per mantenere il codice manutenibile in futuro. E hai ragione che ci sono modi per disaccoppiare ulteriormente MVC. In effetti, il tuo esempio è un po 'come il PAC, ma invece di rimuovere il collegamento V-C, rimuove il collegamento M-V.

In ogni caso, seguire un'architettura, documento l'architettura (in modo che le persone sappiano qual è la tua interpretazione) e non allontanarsi da quello.

+0

Grazie per la risposta. Apprezzo il tuo consiglio e vorrei saperne di più sul modello PAC – pleerock

+0

Chi aggiungerebbe le 'viste' nell'arrayList' modelListeners' nella classe 'MyModel'? Lo farebbe in 'MyController', dove nella classe' MyController' si farebbe 'modello. addModelListener (vista) '? – CapturedTree

+1

Certo, penso che il controller sarebbe il posto giusto in questo esempio sì. Quindi nel costruttore del controllore: 'model.addModelListener (view);' Facoltativamente, si potrebbe avere l'interfaccia 'View' estendere' ModelListener' in modo da sapere che sarà sempre un ascoltatore. Oppure l'interfaccia 'View' implementa un metodo che restituisce il suo' ModelListener'. Ci sono molte opzioni. Come ho detto, scegli un'implementazione e prosegui con essa :) – Brian

Problemi correlati