Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi
Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi
Mate X7 rinnova la sfida nel segmento dei pieghevoli premium puntando su un design ancora più sottile e resistente, unito al ritorno dei processori proprietari della serie Kirin. L'assenza dei servizi Google e del 5G pesa ancora sull'esperienza utente, ma il comparto fotografico e la qualità costruttiva cercano di compensare queste mancanze strutturali con soluzioni ingegneristiche di altissimo livello
Nioh 3: souls-like punitivo e Action RPG
Nioh 3: souls-like punitivo e Action RPG
Nioh 3 aggiorna la formula Team NINJA con aree esplorabili più grandi, due stili di combattimento intercambiabili al volo (Samurai e Ninja) e un sistema di progressione pieno di attività, basi nemiche e sfide legate al Crogiolo. La recensione entra nel dettaglio su combattimento, build, progressione e requisiti PC
Test in super anteprima di Navimow i220 LiDAR: il robot tagliaerba per tutti
Test in super anteprima di Navimow i220 LiDAR: il robot tagliaerba per tutti
La facilità di installazione e la completa automazione di tutte le fasi di utilizzo, rendono questo prodotto l'ideale per molti clienti. Ecco com'è andata la nostra prova in anteprima
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 26-07-2007, 13:54   #1
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
[Java] pattern Model-View-Controller e Swing

Sto provando a mettere in pratica il pattern Model-View-Controller in un'applicazione basata su Swing. Il dilemma è questo:
Come faccio in pratica a notificare alla View qualsiasi modifica al Model?
Più semplicemente:
Esiste una tecnica consolidata per aggiornare tutti i componenti di una gui che visualizzano un dato, quando quest'ultimo viene aggiornato?
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 15:06   #2
mad_hhatter
Senior Member
 
L'Avatar di mad_hhatter
 
Iscritto dal: Oct 2006
Messaggi: 1105
Quote:
Originariamente inviato da carosene Guarda i messaggi
Sto provando a mettere in pratica il pattern Model-View-Controller in un'applicazione basata su Swing. Il dilemma è questo:
Come faccio in pratica a notificare alla View qualsiasi modifica al Model?
Più semplicemente:
Esiste una tecnica consolidata per aggiornare tutti i componenti di una gui che visualizzano un dato, quando quest'ultimo viene aggiornato?
certo, applichi il pattern "observer"
mad_hhatter è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 15:25   #3
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
MVC è una sigla parziale. Il pattern MVC è in verità MNVC, dove N sta per Notifiable. La N è quello che permette al modello di comunicare con le viste senza che le viste possiedano un riferimento al modello.

Riassumento in due righe pseudo-Javesche, lo schema è:

Model:
+addNotifiable(Notifiable n);

Notifiable:
+qualcosaNotify(...dati notificati)

View implements Notifiable, usa Controller

Controller usa Model

Quando il modello subisce una mutazione ad opera del controllo altro non fa che notificare la mutazione agli oggetti registrati come candidati alle notifiche (da cui il nome Notifiable). La vista o è un Notifiable o usa un Notifiable, in ogni caso è indirettamente collegata al modello.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 16:40   #4
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Molte grazie per le risposte.

Ho scartato il modello "observer" perchè impone che l'oggetto osservato estenda Observable. Tutto questo mi limiterebbe nel creare una mia gerarchia di classi.

PGI-Bis è molto interessante quello che mi hai scritto. Potresti farmi un esempio pratico su come implementare il tutto?
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 17:06   #5
mad_hhatter
Senior Member
 
L'Avatar di mad_hhatter
 
Iscritto dal: Oct 2006
Messaggi: 1105
Quote:
Originariamente inviato da carosene Guarda i messaggi
Molte grazie per le risposte.

Ho scartato il modello "observer" perchè impone che l'oggetto osservato estenda Observable. Tutto questo mi limiterebbe nel creare una mia gerarchia di classi.

PGI-Bis è molto interessante quello che mi hai scritto. Potresti farmi un esempio pratico su come implementare il tutto?
in realtà non è necessario che estenda Observable (che a me non piace)... basta che ti fai una semplicissima interface Observable con i metodi addObserver, removeObserver e notifyObservers e un'interface Observer con un metodo update per ricevere le notifiche... così puoi crearti la tua gerarchia senza problemi

inoltre quanto detto da PGI-bis credo vada proprio in quella direzione: quello che lui chiama Notifiable è il mio Observer, mentre il Model è l'observable
mad_hhatter è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 19:18   #6
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Interessante per modo di dire. L'MVC sa un po' di stantìo .

Supponiamo che i dati contenuti nel modello siano... una stringa. Chi volesse ricevere una notifica sull'intervenuta mutazione dei dati del modello potrebbe semplicemente dire d'essere un:

Codice:
public interface ModelNotifiable {

	void dataChangeNotify(String value);
}
Ecco, l'MVC è bell'e che finito.

Il modello è una cosa che ha una stringa e un registro di oggetti "ModelNotifiable". Quando la stringa cambia, il modello piglia e invoca il metodo dataChangeNotify di ogni ModelNotifiable registrato. Per farlo basta una lista.

Codice:
import java.util.*;

public class Model {
	private LinkedList<ModelNotifiable> notifiables = new LinkedList<ModelNotifiable>();
	private String data;
	
	public void addNotifiable(ModelNotifiable n) {
		notifiables.add(n);
	}
	
	public void setData(String value) {
		this.data = value;
		notifyDataChange();
	}
	
	private void notifyDataChange() {
		for(int i = 0; i < notifiables.size(); i++) {
			notifiables.get(i).dataChangeNotify(data);
		}
	}
}
Qui che si fa. Si fa:

Model model = new Model();
model.addNotifiable(la vista);

e fine della storia: a questo punto ogni volta che il modello rileva una mutazione del suo dato, spara un dataChangeNotify, la vista lo riceve e aggiorna la presentazione dei dati. Nulla di trascendentale.

Una vista degna di cotanto modello potrebbe essere:

Codice:
import java.awt.*;
import javax.swing.*;

public class FakeView implements ModelNotifiable {
	private JFrame window = new JFrame("FakeView Frame");
	private JLabel dataLabel = new JLabel("", JLabel.CENTER);
	
	public FakeView() {
		window.add(new JLabel("Valore", JLabel.CENTER), BorderLayout.NORTH);
		window.add(dataLabel, BorderLayout.CENTER);
		window.setPreferredSize(new Dimension(300, 200));
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public void show() {
		EventQueue.invokeLater(new Runnable() { public void run() {
			window.pack();
			window.setLocationRelativeTo(null);
			window.setVisible(true);
		}});
	}

	public void dataChangeNotify(final String value) {
		EventQueue.invokeLater(new Runnable() { public void run() {
			dataLabel.setText(value);
		}});
	}
}
Una finestra con due etichette. Come noti FakeView è un ModelNotifiable. E' il fatto di essere un ModelNotifiable (o di possedere un ModelNotifiable, ma lo MVC "classico" vuole che la vista sia un notificabile) che consente alla vista di presentare dei dati senza avere cognizione del luogo da cui provengono.

Manca il controller. Originariamente (MVC nasce nel campo delle interfacce grafiche con il proposito di separare la presentazione dei dati dal dispositivo di input usato dall'utente) il controllo era un ponte tra l'utente ed il modello.

Ad esempio:

Codice:
public class ConsoleController {
	private Model model;

	public ConsoleController(Model model) {
		this.model = model;
	}
	
	public void start() {
		java.io.Console console = System.console();
		console.printf("Benvenuto nel 1967!%n");
		console.printf("Inserisci una stringa e premi invio%n");
		console.printf("La stringa quit chiude il programma%n");
		String line;
		while(!(line = console.readLine()).equals("quit")) {
			model.setData(line);
		}
		console.printf("Fine dell'interazione%n");
	}
}
Oggi è ancora un ponte tra l'utente ed il modello ma in un modo diverso. Per Controller si intende spesso il componente che si occupa di applicare la logica del programma all'input utente, dove l'input viene catturato dalla vista.

Bisogna stare attenti perchè le due interpretazioni sembrano simili ma non lo sono.

Un esempio di controller per Modello, che usa la console come periferica di input (ai tempi andati il controller avrebbe interagito direttamente con la tastiera), è:

Codice:
public class ConsoleController {
	public void link(Model model) {
		java.io.Console console = System.console();
		console.printf("Benvenuto nel 1967!%n");
		console.printf("Inserisci una stringa e premi invio%n");
		console.printf("La stringa quit chiude il programma%n");
		String line;
		while(!(line = console.readLine()).equals("quit")) {
			model.setData(line);
		}
		console.printf("Fine dell'interazione%n");
	}
}
Il punto d'entrata dell'applicazione MVC mette insieme i tre pezzi. Crea un modello, crea una vista, registra la vista come ricevitore di notifiche dal modello, crea il controllo. Quando il controllo è collegato al modello, l'utente può iniziare ad interagire con l'applicazione.

Codice:
public class Main {

	public static void main(String[] args) {
		Model model = new Model();
		FakeView view = new FakeView();
		model.addNotifiable(view);
		view.show();
		ConsoleController controller = new ConsoleController();
		controller.link(model);
	}
}
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 23:51   #7
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
PGI-Bis sei stato chiarissimo e gentilissimo.
Grazie di cuore…
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 06-08-2007, 18:31   #8
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Sto provando a mettere in pratica il tutto, per realizzare un programma che accede ad un database, visualizza i dati in diverse Jtable, in modo che possano essere modificati.
Per realizzare tutto questo ho creato tre package: Model, View e Controller.
  • Nel primo ho inserito tutte le classi che rappresentano un dato.
  • Nel secondo tutte le classi che si occupano di visualizzare i dati all'utente.
  • Nel terzo una classe che colleghi i primi due strati, e tutte le classi che incapsulano un'interazione con l'utente.
I dubbi sono questi:
Dove vanno inseriti i renderers delle celle?
Chiedo questo perché sono componenti grafici, ma comunque specifici di un modello. Di conseguenza mi riesce difficile immaginare un modo per separarli completamente.
Dove vanno inseriti gli editor di cella?
Al loro interno incapsulano un Component, ma al tempo stesso devono funzionare da controller, perché non tutti i dati inseriti dall'utente possono essere accettati.
Dove bisogna controllare l'input dell'utente?
Nel modello o nel controller?
Come gestire le modifiche dei dati?
In alcune circostanze, potrebbe essere necessario che per accettare una modifica di un determinato dato, ci debba essere una determinata condizione. Dove gestire il tutto: nel modello o nel controller?

Sto pensando a tutto questo perché immagino a come possa essere convertito un programma standalone in “altro”. Questo comporterebbe il rifacimento di tutto il controller e di tutte le viste. Giusto?
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 06-08-2007, 21:57   #9
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
L'input utente è gestito dal controller. Intendo per input l'interazione dell'utente e non la validità delle informazioni immesse dall'utente.

La verifica dell'input è gestita dal modello o dal controllo. Dal modello se la validità dell'immissione dipende da un valore noto al modello. Altrimenti deve essere gestita dal controllo. Tale verifica assume le vesti di una convalida a posteriori solo nel caso di gestione da parte del modello. Nel caso in cui essa sia gestita dal controllo (in quanto non dipendente da uno stato del modello), la verifica è una semplice formattazione dell'input.

Due esempi astratti.

1. Verifica da parte del modello.

Il modello contiene delle chiavi a cui possono essere associati dei valori. Un valore può essere inserito solo se esiste una chiave a cui associare quel valore. L'utente inserisce coppie chiave (esistente) valore (nuovo). Chi controlla che la chiave esista prima di inserire il valore? Il modello. Lo fa il modello perchè la validità dell'input dipende da uno stato del modello (la presenza di una certa chiave).

2. Verifica da parte del controllo.

Il modello contiene numeri interi maggiori di 35. L'utente inserisce 30. Chi controlla che il numero sia maggiore di 35? Il controllo, perchè la validità dell'input non dipende da uno stato del modello. In questo caso il controllo opera come semplice "formattatore" dell'input. E' come se il modello richiedesse una sequenza di caratteri ed il controllo dovesse produrla a partire da una tastiera virtuale gestita col mouse. Il controllo si occupa di ricondurre una varietà di input ad un insieme predefinito di valori ciò che può essere fatto dal controllo in autonomia se e solo se i "limiti" di quell'insieme siano noti a priori. E' chiaro che questo può accadere solo se quei limiti non siano variabili. Nel caso in cui siano variabili, quella variabilità, in quanto informazione, sarà gestita dal modello.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 09:00   #10
Nous
Senior Member
 
Iscritto dal: Oct 2002
Città: Como
Messaggi: 708
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
La verifica dell'input è gestita dal modello o dal controllo. Dal modello se la validità dell'immissione dipende da un valore noto al modello. Altrimenti deve essere gestita dal controllo.
In altre parole, applica il pattern Expert e risolvi tutti i tuoi dubbi...chi deve fare un'operazione? L'esperto per il problema che l'operazione risolve
__________________
Cristian ,il nOUS che invoglia
i5-2500 (Sandy Bridge) Quad-Core 3,30 Ghz - Asus P8Z68-V PRO / GEN3 - 2x4GB DDR3 - GeForce GTX 550 Ti Pci-E 4 Gb ddr3 - Barracuda 7200.12 1 Tb Sata 600 Buffer 32 Mb 7200 Rpm
Nous è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 11:36   #11
pierosa
Member
 
Iscritto dal: Jan 2007
Messaggi: 189
Ti propongo un esmpio semplice di un pattern molto simile al MVC, il pattern Model-View-Presenter(MVP).
In questo pattern Model e View sono gli stessi del MVC e il Controller è chiamto Presenter e si occupa anche di aggirnare la view.
Ci sono 2 varianti quella che ti presento è la Passive View.
Supponiamo di avere un form con 1 campi di testo dove puoi inserire un nome e cliccado su un pulsante esegui una ricerca in una rubrica telefonica, visualizzando il numero di telefono in una label.
Non uso java da troppo tempo per cui l'esempio sarà in pseudocodice simile a java.
Il Model è molto semplice
Codice:
public class Model{
  private String name;
  private String number;
  
  public void SetName(String name){
    this.name = name;
  }
  
  public String getName(){
    return this.name;
  }
  // set e get per number
}
LA view implementa una interfaccia che stabilisce un contratto tra la stessa view e il presenter. Questo ti permette di cambiare view a patto che questa implementi l'interfaccia richiesta
Codice:
public interface ISearchView {
  public void setNumber(String number);
  public void displayError(String error);
}

public class SearchView implements ISearchView {
  private SearchPresenter presenter;
  private JTextField  = new JTextField();
  private JLabel numberLabel = new Jlabel();
  private JLabel errorLabel = new Jlabel();
  private JButton searchButton = new Jbutton();
    
  public SearchView(){
    // ogni view crea un presenter e si inietta nello stesso
    presenter = = new SearchPresenter(this);
  }
  
  public void setNumber(String number){
    numberLabel.setText(number);
  }

  public void displayError(String error){
    errorLabel.setText(error);
  }
  
  public void buttonClick(){
    // al click del bottone la view richiama il metodo search del presenter
    // che si occupa di validare l'input e effettuare le operazioni richieste
    presenter.search(nameTextField.getText());
  }
}
come vedi la view conosce il presenter, nel costruttore crea un nuovo presenter e si inietta nello stesso.

Il presenter non conosce direttamente la view (intesa come implementazione specifica di una view) ma conosce l'interfaccia che essa implementa. Per cui può agire sulla stessa richiedendo delle oprazioni, il modo in cui le operazioni sarranno implementate dipende esclusivamente dalla view. Se devo mostrare un messaggio di errore il presenter esegue la richiesta, ma sarà la view a decidere come visualizzare l'errore (per esempio può visualizzare un testo in una label, oppure inserire un * vicino al campo non validato).
Codice:
public class SearchPresenter{
  private ISearchView view;
  // supponiamo che ModelDao sia una classe che che effettua operazioni su database
  ModelDao dao; 
  Model model;

  public SearchPresenter(ISearchView view){
    this.view = view;
  }
  
  public void search(String name){
    // questo metodo vaiilda l'input 
    // esegue le operazioni di ricerca e aggiorna la view
    // altrimenti notifica alla view di visualizzare un errore
    if (controllo se name è valido){
      model = dao.search(name);
      view.setNumber(model.getNumber());
    } else 
      view.displayError("Inserisci un nome");
  }
}
e poi il main è semplice
Codice:
public class Main {
	public static void main(String[] args) {
		SearchView view = new SearchView();
                view.Show();
	}
}
Ciao
pierosa è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 17:00   #12
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Grazie per i vostri suggerimenti.
Ho tuttavia i seguenti dubbi:
  • Se nel modello si dovesse determinare che l'input è errato, si applica il pattern Observer per avvisare l'utente?
  • Nel pattern MVP, avere l'esigenza dello stesso Presenter in due componenti differenti della gui. È da considerare un errore di design dell'intero applicativo?
  • In entrambi i pattern MVP e MVC dove si gestiscono le meccaniche della gui? Ad esempio: solo se un elemento di un elenco è selezionato, bisogna abilitare un pulsante.
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 17:32   #13
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Le meccaniche della gui si gestiscono nel modello.

La vista fa vedere e stop.

Il pulsante è attivo solo se un elemento della lista è selezionato: significa che nel modello c'è un'informazione "elementoSelezionato" e un'informazione "stato del pulsante", che la mutazione del valore "elementoSelezionato" causa una mutazione del valore "stato del pulsante". Queste mutazioni sono comunicate alla vista tramite Notifiable e la vista aggiorna il suo aspetto in conseguenza della notifica ricevuta.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 17:57   #14
pierosa
Member
 
Iscritto dal: Jan 2007
Messaggi: 189
Nel Passive view tutte le dinamiche della view sono gestite dal presenter (la vista è passiva, come dal nome)
all'evento della selezione della lista richiami il presenter notificandogli l'evento e di conseguenza il presenter richiederà l'aggiornamento della view attivando il bottone.
Quote:
Nel pattern MVP, avere l'esigenza dello stesso Presenter in due componenti differenti della gui. È da considerare un errore di design dell'intero applicativo?
non ho ben capito cosa intendi
pierosa è offline   Rispondi citando il messaggio o parte di esso
Old 10-08-2007, 18:00   #15
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Scusatemi per il ritardo con il quale sto rispondendo.
Ho cercato di mettere in pratica il tutto, creando una semplice rubrica con il pattern MVP. Il programma non è di alcuna utilità, mi è servito solo per esercitarmi. Tecnicamente consente di aggiungere o rimuovere un contatto ad una collection, attraverso una JTable.
Mi piacerebbe molto avere qualsiasi vostro commento, perchè non sono un professionista o uno studente, ma un semplice hobbysta.

Quote:
Originariamente inviato da pierosa Guarda i messaggi

non ho ben capito cosa intendi
Volevo chiedere: Nel caso in cui un presenter dovesse gestire più di una finestra, non sarebbe più possibile crearlo nel costruttore della finestra. Come fare?
Allegati
File Type: zip MVP.zip (6.1 KB, 9 visite)
carosene è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi Recensione HUAWEI Mate X7: un foldable ottimo, m...
Nioh 3: souls-like punitivo e Action RPG Nioh 3: souls-like punitivo e Action RPG
Test in super anteprima di Navimow i220 LiDAR: il robot tagliaerba per tutti Test in super anteprima di Navimow i220 LiDAR: i...
Dark Perk Ergo e Sym provati tra wireless, software via browser e peso ridotto Dark Perk Ergo e Sym provati tra wireless, softw...
DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker DJI RS 5: stabilizzazione e tracking intelligent...
Sembra ormai certo: la prossima Xbox sar...
“Solutions Beyond Displays”: la strategi...
La società europea The Exploratio...
Dalle auto ai robot umanoidi: Faraday Fu...
Vodafone annuncia la dismissione di un s...
Stiga lancia i nuovi robot tagliaerba co...
Bullismo e cyberbullismo, Keenetic lanci...
Con AI Skills Checker Bitdefender mette ...
E-bike giapponese con 1.000 km di autono...
Un eVTOL con cui basta saper andare in b...
Dal mercato cinese al mondo: HONOR firma...
Sovranità digitale: l'UE sperimen...
Accesso alla memoria su Windows 11 solo ...
iPhone 18 Pro Max con batteria da oltre ...
Windows 11, cali di prestazioni sulle GP...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 23:03.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v