Einführung Inhaltsverzeichnis 2. Darstellung von Variablen und Werten

6. Generisches MVC

Das Problem der Verbindung der Lauscher mit allen Views erfordert ein generisches MVC-Konzept. Die Idee dabei ist, dass ein enum alle Ereignisse aufzählt, die von einer Oberfläche kommen können. Zu jedem Ereignis wird ein Lauscher-Objekt zugeordnet, deren einzige Methode aktion() auf dieses Ereignis reagiert. Diese Zuordnung kann z.B. in einer Map erfolgen. Die setLauscher-Methode von IView bekommt als Parameter so ein Map:

package uhrMVC;

 import java.util.Map;

 public interface IView { IView.java

   enum Ereignis { EIN, AUS, UM }

   static interface Lauscher { void aktion(); }

   void setLauscher(Map<Ereignis, Lauscher> lauscher);

   void tick();

   void start();

   void stopp(); }

Im Konstruktor des für alle Views gemeinsamen Controls wird das Map-Objekt erzeugt und allen Views übergeben:

public Control(final IModel model, final IView[] views) { // Control.java

   Map<Ereignis, Lauscher> lauscher = new EnumMap<Ereignis, Lauscher>(Ereignis.class); // EnumMap braucht ein Class-Objekt als Konstruktorparameter

   lauscher.put(Ereignis.EIN, new Lauscher() {

     @Override

     public void aktion() {

        model.start();

        for (IView view : views)

           view.start(); } });

   lauscher.put(Ereignis.AUS, new Lauscher() {

     @Override

     public void aktion() {

        model.stopp();

        for (IView view : views)

           view.stopp(); } });

   lauscher.put(Ereignis.UM, new Lauscher() {

     @Override

     public void aktion() {

        model.umschalten(); } });

   for (IView view : views)

      view.setLauscher(lauscher);

   new Thread() { … // wie gehabt

Jede View bekommt also alle Lauscher und fügt selber ihrer Darstellung hinzu:

public class DigitalView extends JFrame implements IView { // DigitalView.java

   // Variablen und Konstruktor ähnlich wie in DigitalUhr

   @Override

   public void setLauscher(final Map<Ereignis, Lauscher> lauscherMap) {

     knopfEin.addActionListener(new ActionListener() {

        @Override

        public void actionPerformed(ActionEvent e) {

           lauscherMap.get(Ereignis.EIN).aktion(); } });

     knopfAus.addActionListener(new ActionListener() {

        @Override

        public void actionPerformed(ActionEvent e) {

           lauscherMap.get(Ereignis.AUS).aktion(); } });

     knopfUm.addActionListener(new ActionListener() {

        @Override

        public void actionPerformed(ActionEvent e) {

           lauscherMap.get(Ereignis.UM).aktion(); } }); }

sowie

public class KreisView extends JFrame implements IView { // KreisView.java

   // Variablen und Konstruktor ähnlich wie in KreisUhr

   @Override

   public void setLauscher(final Map<Ereignis, Lauscher> lauscherMap) {

     super.addKeyListener(new KeyAdapter() {

        @Override

        public void keyPressed(KeyEvent e) {

           switch (e.getKeyChar()) {

           case 'E': // "Ein"

              lauscherMap.get(Ereignis.EIN).aktion();

              break;

           case 'A': // "Aus"

              lauscherMap.get(Ereignis.AUS).aktion();

              break;

           case 'U': // "Um"

              lauscherMap.get(Ereignis.UM).aktion();} } });  } }

In main wird nun Control mit einer Reihung aus allen Views instanziiert:

public static void main(String[] args) { // Main.java

   IModel model = new Model();          

   new Control(model, new IView[] {

     new KreisView(model), new DigitalView(model) }); }

Wenn Views dynamisch (zur Laufzeit) hinzugefügt werden können sollen, muss man statt der Reihung ArrayList benutzen.

Das Entwurfsmuster Observer

Einführung Inhaltsverzeichnis 2. Darstellung von Variablen und Werten


Version: 19. April 2012

© Prof. Solymosi, 20102 Beuth-Hochschule für Technik Berlin, Fachbereich VI (Informatik und Medien)

solymosibht-berlin.de