IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

MVC sur application de gestion produit


Sujet :

Java

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 181
    Points : 80
    Points
    80
    Par défaut MVC sur application de gestion produit
    Bonjour
    Je suis entrain de travailler sur une application de gestion produit et je souhaite la travailler avec le pattern MVC
    J'ai commencé par créer ma classe produit dans le package modele :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    package ma.vente.model;
     
    public class Produit {
    	private Integer ref_produit;
    	private String libelle_produit;
    	private String date_production;
    	private Double prix;
     
    	public Produit(Integer ref_produit, String libelle_produit, String date_production, Double prix) {
    		super();
    		this.ref_produit = ref_produit;
    		this.libelle_produit = libelle_produit;
    		this.date_production = date_production;
    		this.prix = prix;
     
    	}
     
    	public Integer getRef_produit() {
    		return ref_produit;
    	}
     
     
    	public void setRef_produit(Integer ref_produit) {
    		this.ref_produit = ref_produit;
    	}
     
    	public String getLibelle_produit() {
    		return libelle_produit;
    	}
     
    	public void setLibelle_produit(String libelle_produit) {
    		this.libelle_produit = libelle_produit;
    	}
     
    	public String getDate_production() {
    		return date_production;
    	}
     
    	public void setDate_production(String date_production) {
    		this.date_production = date_production;
    	}
     
    	public Double getPrix() {
    		return prix;
    	}
    	public void setPrix(Double prix) {
    		this.prix = prix;
    	}
     
    }
    Par contre dans la package controle je sais pas que dois je faire a fin de faire la liaison avec le package vue et modele
    Qui ce que la classe controle doit contenir
    PS : je ferais une application disktop pour le début

    Merci d'avance

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,


    Le controleur est étroitement lié à la vue, aussi bien qu'au modèle. La vue est composée :
    • de composant d'affichage de données du modèle
    • de composant de modification de données du modèle
    • de composant réalisant des actions


    Le controlleur doit connaître les composants dans la vue, et savoir à quelle donnée chacun est associée, afin :
    • d'initialiser la champ avec la bonne valeur
    • d'affecter la donnée du modèle avec la valeur du bon champ

    C'est lui qui gère les actions (la vue ne doit juste que savoir quelles actions existent) et fournit les services annexes (comme la validation par exemple : ce n'est pas à la vue de savoir si les données sont obligatoires ou facultatives, ou s'il faut saisir un nombre > 0 par exemple).

    En gros, la vue va construire ses composants et en avertir le controleur qui en retour va se brancher dessus pour réagir et mettre à jour le modèle le cas échéant.

    Parfois, le controleur est tellement lié à la vue, que c'est une classe interne, qu'on ne peut manipuler à part. Cela simplifie souvent l'implémentation des interactions entre les deux, mais ça oblige à avoir un modèle générique pour la vue (on peut utiliser une interface par exemple).

    Bien sûr, le modèle ne doit ni avoir connaissance de la vue, ni du contrôleur.

    Par exemple, prenons un modèle à 2 propriétés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class Personne {
     
    	private String nom;
    	private String prenom; 
     
    	public Personne() { 
    	}
     
    	public void setNom(String nom) {
    		this.nom=nom;
    	}
     
    	public String getNom() {
    		return nom;
    	}
     
    	public void setPrenom(String prenom) {
    		this.prenom = prenom;
    	}
     
    	public String getPrenom() {
    		return prenom;
    	} 
     
    }
    Voici un controleur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    public class VueCreerPersonneControleur {
     
    	public static final String NOM = "nom";
    	public static final String PRENOM = "prenom";
    	public static final String DIRTY = "dirty"; 
    	public static final String VALID = "valid"; 
     
    	private final Personne personne;
    	private final SwingPropertyChangeSupport propertyChangeSupport; // on utilise ça pour gérer les évenements
    	private final Map<String, String> changed; // stocke les modifications du modèle sans modifier le modèle
    	private boolean valid;
     
    	public VueCreerPersonneControleur(Personne personne) {
    		this.propertyChangeSupport=new SwingPropertyChangeSupport(this);
    		this.personne=personne;
    		this.changed=new HashMap<>();
    		this.valid=isValid();
    	}
     
    	// cette méthode permet de lier vue et controleur
    	public PropertyChangeListener add(String property, PropertyChangeListener modelChangeListener) {
    		switch(property) {
    		case DIRTY:
    		case VALID:
    			propertyChangeSupport.addPropertyChangeListener(property, modelChangeListener);
    			return null;
    		case NOM:
    		case PRENOM:
    			propertyChangeSupport.addPropertyChangeListener(property, modelChangeListener);
    			propertyChangeSupport.firePropertyChange(property, null, getProperty(property)); // initialise le champ
    			return e-> {
    				propertyChanged(property, getProperty(property), (String)e.getNewValue() );
    			};
    		default:
    			throw new IllegalArgumentException("Propriété inconnue");
    		}
    	} 
     
    	// sauve les changements de la vue dans le controleur, temporairement, et gère les états dirty et invalid 
    	private void propertyChanged(String property, String oldValue, String newValue) {
    		boolean empty = changed.isEmpty();
    		if ( Objects.equals(oldValue, newValue) ) {
    			changed.remove(property);
    		}
    		else {
    			changed.put(property, newValue);
    		}
    		if ( changed.isEmpty()!=empty ) {
    			propertyChangeSupport.firePropertyChange(DIRTY, empty, !empty);
    		}
    		isValid();
    	}
     
    	// test si quelque chose est modifié
    	public boolean isDirty() {
    		return !changed.isEmpty();
    	}
     
    	// permet d'associer propriété et modèle
    	private String getProperty(String property) {
    		String value=null;
    		switch(property) {
    		case NOM:
    			value = personne.getNom();
    		case PRENOM:
    			value = personne.getPrenom();
    		}
    		if ( value==null ) {
    			value="";
    		}
    		return value;
    	} 
     
    	// une action de sauvegarde fourni par le controleur
    	public void save() {
    		if ( isDirty() ) {
    			if ( changed.containsKey(NOM) )  {
    				personne.setNom(changed.get(NOM));
    			}
    			if ( changed.containsKey(PRENOM) )  {
    				personne.setPrenom(changed.get(PRENOM));
    			}
    			changed.clear();
    			isValid();
    		}
    	}
     
    	// teste si la saisie est valide
    	public boolean isValid() {
    		boolean old=valid;
    		valid = isValid(NOM) && isValid(PRENOM); 
    		if ( old!=valid ) {
    			propertyChangeSupport.firePropertyChange(VALID, old, valid);
    		}
    		return valid;
    	}
     
    	// teste si la propriété est valide
    	private boolean isValid(String property) {
    		if ( changed.containsKey(property) ) {
    			if  (changed.get(property).trim().isEmpty() ) {
    				return false;
    			}
    		}
    		else {
    			if ( getProperty(property)==null || getProperty(property).trim().isEmpty() ) {
    				return false;
    			}
    		}
    		return true;
    	}
     
    	// une action fournie par le controlleur pour remettre à zéro
    	public void reset() {
    		propertyChangeSupport.firePropertyChange(NOM, changed.get(NOM), getProperty(NOM));
    		propertyChangeSupport.firePropertyChange(PRENOM, changed.get(PRENOM), getProperty(PRENOM));
    	}
     
    }
    La vue associée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    public class VueCreerPersonne extends JDialog {
     
    	private final VueCreerPersonneControleur controleur;
     
    	public VueCreerPersonne(JFrame frame, VueCreerPersonneControleur controleur) {
    		super(frame,true);
     
    		this.controleur = controleur;
     
    		setTitle("Modifier personne");
     
    		JPanel panel = new JPanel(new GridBagLayout());
    		Insets insets = new Insets(2,2,2,2);
     
                    // la vue décide quelles informations elle affiche et permet de modifier
    		panel.add(new JLabel("Nom :"), new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.EAST,GridBagConstraints.NONE,insets,0,0));
    		panel.add(new JLabel("Prenom :"), new GridBagConstraints(0,1,1,1,0,0,GridBagConstraints.EAST,GridBagConstraints.NONE,insets,0,0));
    		JTextField nomField = new JTextField();
    		JTextField prenomField = new JTextField();
    		panel.add(nomField, new GridBagConstraints(1,0,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,insets,0,0));
    		panel.add(prenomField, new GridBagConstraints(1,1,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,insets,0,0));
     
                    // fait le lien entre vue et controleur
    		register(VueCreerPersonneControleur.NOM, nomField);
    		register(VueCreerPersonneControleur.PRENOM, prenomField);
     
    		getContentPane().setLayout(new BorderLayout());
    		getContentPane().add(panel);
     
    		JPanel buttonPanel = new JPanel();
    		JButton buttonReset = new JButton("Reset");
    		buttonReset.addActionListener(e-> controleur.reset());
    		buttonPanel.add(buttonReset);
    		JPanel okCancelPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    		JButton buttonOk = new JButton("Sauver");
    		buttonOk.addActionListener(e-> {
    			controleur.save();
    			VueCreerPersonne.this.dispose();
    		});
    		okCancelPanel.add(buttonOk);
    		buttonOk.setEnabled(false);
                    // le controleur propose d'autres informations que celles du modèles pour améliorer le fonctionnement de la vue (ici un état dirty=saisie non sauvegardée, un état valid=saisie valide)
    		controleur.add(VueCreerPersonneControleur.DIRTY, e-> {
    			buttonOk.setEnabled((boolean)e.getNewValue()&&controleur.isValid());
    		});
    		controleur.add(VueCreerPersonneControleur.VALID, e-> {
    			buttonOk.setEnabled((boolean)e.getNewValue()&&controleur.isDirty());
    		});
    		JButton buttonCancel = new JButton("Annuler");
    		buttonCancel.addActionListener(e-> {
    			VueCreerPersonne.this.close();
    		});
    		okCancelPanel.add(buttonCancel);
    		buttonPanel.add(okCancelPanel);
    		getContentPane().add(buttonPanel, BorderLayout.SOUTH);
     
    		pack();
    		setLocationRelativeTo(null);
     
    		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    		addWindowListener(new WindowAdapter() {
     
    			@Override
    			public void windowClosing(WindowEvent arg0) {
    				close(); // permet d'intercepter la fermeture par la croix
    			}
    		});
     
    	}
     
             // fermeture du dialogue
    	protected void close() {
    		if ( controleur.isDirty() ) {
    			switch( JOptionPane.showConfirmDialog(VueCreerPersonne.this, "Voulez-vous enregistrer vos modifications ?")) {
    			case JOptionPane.OK_OPTION:
    				if ( !controleur.isValid() ) {
    					JOptionPane.showMessageDialog(VueCreerPersonne.this, "Saisie invalide");
    				}
    				else {
    					controleur.save();
    					VueCreerPersonne.this.dispose();
    				}
    				break;
    			case JOptionPane.NO_OPTION:
    				VueCreerPersonne.this.dispose();
    				break;
    			}
    		}
    		else {
    			VueCreerPersonne.this.dispose();
    		}
    	}
     
            // associe le controleur et la vue
    	private void register(String property, JTextField field) {
    		PropertyChangeListener listener = controleur.add(property, p-> field.setText((String)p.getNewValue()));
    		field.getDocument().addDocumentListener(new DocumentListener() {
     
    			@Override
    			public void removeUpdate(DocumentEvent arg0) {
    				update();
    			}
     
    			@Override
    			public void insertUpdate(DocumentEvent arg0) {
    				update();
    			}
     
    			@Override
    			public void changedUpdate(DocumentEvent arg0) {
    				update();
    			}
     
    			private void update() {
    				//SwingUtilities.invokeLater(()->					
    			    listener.propertyChange(new PropertyChangeEvent(this, property, null, field.getText()));
    			}
    		});
    	}
     
    }
    Et le programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public class Exemple {
     
    	public static void main(String[] args) {
     
    		JFrame frame = new JFrame("Application"); // une fenêtre pour l'application
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JPanel panel = new JPanel();
    		JButton button = new JButton("Créer personne"); // un bouton pour une action avec un MVC
    		button.addActionListener(e-> {
    			Personne personne = new Personne();  // on créer le modèle
     
    			new VueCreerPersonne(frame, new VueCreerPersonneControleur(personne)).setVisible(true); // on crée le controleur et la vue
     
    			// on affiche le contenu du modèle (on pourra faire évoluer la vue pour savoir si on a fait ok ou cancel)
    			System.out.println("Nom : " + personne.getNom());
    			System.out.println("Prenom : " + personne.getPrenom());
     
    		});
    		panel.add(button);
     
    		// on affiche
    		frame.getContentPane().add(panel);
    		frame.setSize(300, 300);
    		frame.setLocationRelativeTo(null);
     
    		frame.setVisible(true);
     
     
    	}
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 181
    Points : 80
    Points
    80
    Par défaut
    Bonsoir,

    Merci pour tes explications clair ainsi que l'exemple fourni avec par contre j'ai quelques questions

    Quand tu dis : "Parfois, le controleur est tellement lié à la vue, que c'est une classe interne, qu'on ne peut manipuler à part. Cela simplifie souvent l'implémentation des interactions entre les deux, mais ça oblige à avoir un modèle générique pour la vue (on peut utiliser une interface par exemple). " J'ai pas compris comment il peut etre une classe interne alors que chacun fait un traitement a part et joue un role différents par contre effectivement j'ai vu plein d'exemple utilisant des interfaces
    et Sinon le MAP tu l'as utilisé juste pour faire le test sur les properties avant de les affecté au modèle ou c'est pour une autre raison ?

    D'avance merci

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par dibax10 Voir le message


    Quand tu dis : "Parfois, le controleur est tellement lié à la vue, que c'est une classe interne, qu'on ne peut manipuler à part. Cela simplifie souvent l'implémentation des interactions entre les deux, mais ça oblige à avoir un modèle générique pour la vue (on peut utiliser une interface par exemple). " J'ai pas compris comment il peut etre une classe interne alors que chacun fait un traitement a part et joue un role différents par contre effectivement j'ai vu plein d'exemple utilisant des interfaces
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public class Vue extends JPanel { // par exemple
     
        private Controleur controleur;
     
        private JTextField field; // par exemple
     
       public Vue(Model model) {
     
               field = new JTextField(); 
     
              controleur = new Controleur(model);
     
       }
     
       // class interne
       private class Controleur {
     
              private final Model model;
              public Controleur(Model model) {
                   this.model=model;
                   field.setText( model.getNom() ); // le controleur a un accès directe au composant de la vue
              }
     
       }
     
     
    }
    Ils jouent bien un rôle différent, mais la classe de Controleur est interne à la classe de Vue, complètement lié à celle-ci. Si le modèle n'est pas générique (interface) alors il faudra une vue+controleur pour chaque modèle, alors que dans le cas que je t'ai montré hier, tu peux réutiliser le controleur avec d'autres vues.

    Citation Envoyé par dibax10 Voir le message
    et Sinon le MAP tu l'as utilisé juste pour faire le test sur les properties avant de les affecté au modèle
    Oui. Une sorte de sas pour ne pas modifier directement le modèle. On pourrait directement modifier le modèle, et gérer le reset et l'annulation différement (par copie de sauvegarde), ou ne pas le gérer aussi. On peut procéder différemment, en faisant que le controleur puisse récupérer directement les champs de la vue (par injection de supplier, ou simplement par interface, ce qui est juste un peu moins flexible). On peut aussi utiliser une autre instance de modèle comme sas à la place de la map. La map permet juste de stocker facilement des propriétés de tout type associé avec des noms de propriétés (donc facile de factoriser les traitements relatifs aux évenements), elle est facile à traiter par boucle aussi. On pourrait facilement faire un controleur qui s'adapte à diférents modèles (qui n'aurait juste qu'à renseigner la liste des propriétés disponibles et les fonctions getters et setters associées, ce qu'on appelle du binding).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 181
    Points : 80
    Points
    80
    Par défaut
    Merci pour les explications.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MVC] Erreur lors intégration Spring MVC sur une application JEE
    Par khaigo dans le forum Spring Web
    Réponses: 0
    Dernier message: 26/06/2011, 18h04
  2. Gestion de vues sur Application "Universal"
    Par Yoite dans le forum Développement iOS
    Réponses: 1
    Dernier message: 22/11/2010, 09h18
  3. Gestion de droits sur application VB Access
    Par tribaleur dans le forum Sécurité
    Réponses: 7
    Dernier message: 18/04/2008, 15h35
  4. Application de gestion des sms sur PC
    Par andyvo dans le forum Langage
    Réponses: 9
    Dernier message: 20/10/2005, 23h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo