2017-04-17 1 views
0

Ich habe 2 Anwendungen:Wie man Schalter mit Polymorphismus ersetzt?

es mehrere Arten application_1 und applicaion_2

appplication_1 zu application_2 Nachrichten unterschiedlicher Typen sendet. Ich kann enum dieser Typen deklarieren.

enum MessageType{ 
    TYPE_1, 
    TYPE_2, 
    ... 
} 

In application_2 Rahmen schlage ich vor, mich API

folgende schreiben verwenden
public void handle(Object o){ 
    //logic 
} 

ich darüber nachdenken, wie Klassen zu bauen jede Nachricht einzeln zu verarbeiten.

Ich verstehe, dass ich allgemeinste Art für alle Nachrichten erklären können:

abstract class AbstractMessage{ 
    MessageType type; 
    Object o; 
    //... 
} 

und in application_2 Innengriff ich smth so schreiben kann:

MessageType mt = ((AbstractMessage) o).getType(); 
    switch(mt){ 
    case TYPE_1: 
     //handle TYPE_1 
     break; 
    case TYPE_2: 
     //handle TYPE_2 
     break; 
     .... 
    } 

Aber dieser Code hässlich aussieht.

Bitte helfen Sie, eine bessere Lösung zu finden.

+1

@Downvoter, bitte erläutern, was Sie nicht verstanden haben. Ich bin bereit, meine Frage zu verbessern. Ich habe wirklich versucht, klare Frage zu stellen – gstackoverflow

+0

Es scheint, was Sie suchen, ist das [Strategie Muster] (https://en.wikipedia.org/wiki/Strategy_pattern#Java). –

+0

@Thomas Fritsch, vielleicht aber könntest du ein bisschen mehr Details geben? – gstackoverflow

Antwort

0

application_2 sowieso muss wissen, welche Art von Nachricht es erhalten hat, so dass eine Art von switch unvermeidlich ist. Aber das Wichtigste ist, dies switchnur an einer Stelle zu haben. Zum Beispiel könnten Sie haben Methode wie folgt vor:

public MessageHandler getHandlerFor(MessageType messageType) { 
    switch (messageType) { 
     case TYPE_1: return Type1MessageHandler(); 
     case TYPE_2: return Type2MessageHandler(); 
     ............ 
     default: throw new IllegalArgumentException("No handler found for messageType: " + messageType); 
    } 
} 

Dann werden Sie die Hierarchie der MessageHandler ‚s benötigen, die Strategie Muster entsprechen:

public interface MessageHandler { 
    void handle(); 
} 

Jede Implementierung MessageHandler Schnittstelle MessageType bieten sollte -spezifische Verarbeitungslogik.

4

Wenn Sie polymorfism verwenden möchten können Sie die abstract Nachrichtenklasse definieren:

abstract class AbstractMessage { 
    public abstract void doStuff(); 
    //... 
} 

statt enums zu verwenden, erstellen Sie eine Klasse für jeden Nachrichtentyp die abstrakte Klasse erweitern und Überschreiben der Methoden:

class Type1Message extends AbstractMessage { 
    @Override 
    public void doStuff() { 
     //handle TYPE_1 
    } 
} 

class Type2Message extends AbstractMessage { 
    @Override 
    public void doStuff() { 
     //handle TYPE_2 
    } 
} 

dann in Ihrer handle Methode:

((AbstractMessage) o).doStuff(); 
+2

Ich denke, Nachricht selbst sollte nicht wissen, wie es behandelt wird. Das ist die Verantwortung des Client-Codes zu entscheiden, was mit jeder Art von Nachricht zu tun ist. –

+1

@ PavloViazovskyy gut, es hängt davon ab, denke ich; auch dies vermeidet die "switch" was OP angefordert –

+0

Sieht aus wie wir haben 2 Hierarchien. Handler und Nachrichten. Kann Brücke helfen? – gstackoverflow

0

Sie können das Muster chain-of-responsibility verwenden. Es unterscheidet sich von dem Strategie-Muster darin, dass Ihre Nachrichten Befehle anzeigen, die jede Anwendung ausführt. Dies ist im Wesentlichen was switch tut.

Sie Klassen dynamisch geladen werden, die eine Schnittstelle mit Ihrem handle Methode implementieren (Pavlo Klasse arbeitet mit einigen Änderungen mit Loris' abstrakte Nachricht zu kombinieren):

public interface MessageHandler 
{ 
    void handle (AbstractMessage msg); 
} 

Java das Konzept eines service provider hat, der ist Methode für dynamisches Laden (Ich bin mir sicher, dass es andere Methoden gibt, die verwendet werden können, wenn dies nicht Ihren Bedürfnissen entspricht). Sie können die Handler zu dem Zeitpunkt durchlaufen, zu dem die Nachricht verarbeitet wird, indem Sie jedem Handler die Nachrichteninstanz übergeben. Jeder Handler entscheidet, ob er die Nachricht behandeln möchte oder nicht. Sie könnten sogar handle eine boolean zurückgeben, um anzuzeigen, dass die Kette aufhören kann, nachfolgende Handler aufzurufen, wenn Sie dies wünschen.

Sie können in jeder Anwendung Handler für die Nachrichtentypen implementieren, die Sie behandeln möchten. Es gibt viele Möglichkeiten, dies zu tun (laden Sie die Handler und initialisieren sie beim Start, laden Sie sie zum Zeitpunkt der Nachrichtenbehandlung, etc.), also wählen Sie die, die Ihrem Bedarf entspricht. Der Artikel zu den verknüpften Dienstanbietern enthält eine einfache Schleife, die das Laden der Handler zeigt.

Keine Notwendigkeit für eine switch, die ändert, wie Ihr Code geändert wird, konfigurieren Sie einfach neu, wie Ihr Glas gebaut wird. Dies ist auch ein gutes Beispiel für die open-closed principle, wo Ihr Code nicht ändert, aber offen für Erweiterung ist.

0

vielleicht etwas wie unten. Es hat einen Schalter, aber der Code für jeden Typ ist zusammen in der Enumeration.

public class So43459907 { 
    public enum Type { 
     m1 { 
      @Override Object create(Object o) { 
       return o; 
      } 
      @Override void handle(Object o) {} 
     }, 
     m2 { 
      @Override Object create(Object o) { 
       return o; 
      } 
      @Override void handle(Object o) {} 
     }; 
     abstract Object create(Object o); 
     abstract void handle(Object o); 
     public static Object create(Type type,Object o) { 
      switch(type) { 
       case m1: 
        return m1.create(o); 
       case m2: 
        return m2.create(o); 
       default: 
        throw new RuntimeException("oops"); 
      } 
     } 
    } 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
    } 
}