Erinnerst du dich noch daran, wie die Gangster im Polizei- und Gangsterfilm zusammengearbeitet haben? Wenn eine Bande Einbruch ist, nehmen ein oder zwei Menschen immer den Wind an der Tür. Bei Bewegung werden die Komplizen im Inneren sofort benachrichtigt, um sich dringend zurückzuziehen. Vielleicht kennt die Person, die die Nachrichten zulässt, nicht unbedingt jeden Komplizen darin; Und es kann einen neuen jüngeren Bruder geben, der nicht denjenige kennt, der die Nachrichten lässt. Dies ist jedoch nichts, es kann ihre Kommunikation nicht beeinflussen, weil sie einen Code haben, der vereinbart wurde.
Haha, die Beziehung zwischen dem Luftprach und dem oben erwähnten Dieb ist ein lebendiges Beispiel für das Beobachtermuster in der Realität.
Der Observer -Modus wird auch als Publish/Abonnement -Modus bezeichnet. GOF definiert das Beobachtermuster wie folgt: definiert eine Eins-zu-Viele-Abhängigkeit zwischen Objekten. Wenn sich der Status eines Objekts ändert, werden alle Objekte, die davon abhängen, benachrichtigt und automatisch aktualisiert.
Hier werde ich zuerst über ein wichtiges Prinzip des objektorientierten Designs sprechen - das Prinzip der einzigen Verantwortung. Daher sollte sich jedes Objekt des Systems auf diskrete Abstraktionen im Problembereich konzentrieren. Im Idealfall macht ein Objekt nur eine Sache. Dies bringt viele Vorteile in der Entwicklung: Es bietet Wiederverwendbarkeit und Wartung und ist auch eine gute Grundlage für das Refactoring.
Daher basieren fast alle Designmuster auf diesem grundlegenden Designprinzip. Ich denke, der Ursprung des Beobachtermodells sollte in der Verarbeitung von GUI- und Geschäftsdaten liegen, da die meisten Beispiele, die das Beobachtermodell erklären, jetzt dieses Thema sind. Die Anwendung des Beobachtermodus ist jedoch keineswegs auf diesen Aspekt beschränkt.
Nun, das Verständnis der Definition erfordert immer Instanzen, um zu analysieren. WeChat -Servicekonten sind heutzutage sehr beliebt. Lassen Sie uns Ihnen das Observer -Modell mit dem Hintergrund von WeChat -Service -Konten vorstellen.
Schauen Sie sich ein Bild an:
Jeder Benutzer verfügt über 3 Zeilen im obigen Bild, die weggelassen werden, um das Bild klar zu machen.
Wie im obigen Bild gezeigt, ist die Servicenummer unser Thema und der Benutzer ist der Beobachter. Jetzt klären wir die folgenden Funktionen:
1. Servicekonto ist das Thema, und Business drückt Nachrichten
2. Beobachter müssen das Thema nur abonnieren, und sie werden gesendet, sobald es neue Nachrichten gibt.
3.. Abbestellen, wenn Sie diese Themennachricht nicht möchten
4. Solange das Servicekonto noch vorhanden ist, wird jemand abonniert. Schauen wir uns nun das Klassendiagramm des Observer -Musters an:
Als nächstes simulieren wir ein WeChat 3D Lottery Service -Konto und einige Abonnenten.
Beginnen Sie zunächst mit dem Schreiben über unsere Themenoberfläche und die Observer -Schnittstelle:
Paket com.zhy.pattern.observer; / ** * Themenschnittstelle, alle Themen müssen diese Schnittstelle implementieren * * @Author ZHY * */ Public Interface Betreff {/ ** * Registrieren Sie einen Beobachter * * @param Beobachter */ public void RegisterObserver (Beobachterbeobachter); / ** * einen Beobachter entfernen * * @param Observer */ public void removeObserver (Beobachter Observer); / *** alle Beobachter benachrichtigen*/ public void musifyObServers (); } paket com.zhy.pattern.observer; / *** @Author ZHY Alle Beobachter müssen diese Schnittstelle implementieren*/ öffentliche Schnittstelle Beobachter {public void Update (String msg); }Nächste 3D -Service -Nummer -Implementierungsklasse:
Paket com.zhy.pattern.observer; Import Java.util.ArrayList; importieren java.util.list; public class ObjectFOR3D implementiert Betreff {private Liste <Beerver> Observers = New ArrayList <Beerver> (); / *** 3D Lotterie Nummer*/ private String msg; @Override public void RegisterObserver (Beobachter Observer) {Beobachter.Add (Beobachter); } @Override public void removeObserver (Beobachter Observer) {int index = Beobachter.Indexof (Beobachter); if (index> = 0) {Beobachter.Remove (index); }} @Override public void benachObServers () {für (Observer Observer: Beobachter) {observer.update (msg); }} / ** * Thema Update -Nachricht * * @param msg * / public void setmsg (String msg) {this.msg = msg; NotifyObServers (); }}Simulieren Sie zwei Benutzer:
Paket com.zhy.pattern.observer; öffentliche Klasse Observer1 implementiert Observer {privates Thema; public Observer1 (Subjekt) {this.subject = Subjekt; Betreff.registerObserver (dies); } @Override public void update (String msg) {System.out.println ("Observer1 erhält die 3D -Nummer ->" + msg + ", ich möchte es aufschreiben."); }} Paket com.zhy.pattern.observer; öffentliche Klasse Observer2 implementiert Observer {privates Thema; public Observer2 (Subjekt) {this.subject = Subjekt; Betreff.registerObserver (dies); } @Override public void update (String msg) {System.out.println ("Observer2 erhält die 3D -Nummer ->" + msg + "Ich möchte meinen Mitbewohnern sagen."); }} Es ist zu erkennen, dass alle Benutzer, die Nachrichten, die sie abonnieren, im Servicekonto verwaltet werden und alle Benutzer benachrichtigt werden, wenn im Service -Konto eine neue Nachricht vorhanden ist. Die gesamte Architektur ist eine lockere Kopplung, und die Implementierung des Themas hängt nicht vom Benutzer ab. Wenn ein neuer Benutzer hinzugefügt wird, muss der Code des Themas nicht geändert werden. Wie der Benutzer die erhaltenen Daten verarbeitet, hat nichts mit dem Thema zu tun.
Schauen Sie sich zum Schluss den Testcode an:
Paket com.zhy.pattern.observer.test; import com.zhy.pattern.observer.objectfor3d; import com.zhy.pattern.observer.observer; import com.zhy.pattern.observer.observer1; import com.zhy.pattern.observer.observer2; import com.zhy.pattern.observer.subject; public class test {public static void main (String [] args) {// Simulieren Sie ein 3D -Dienstnummer ObjectFOR3D Prob. // Customer1 Observer Observer1 = neuer Observer1 (Subjekt für 3D); Observer Observer2 = New Observer2 (Subjekt für 3D); Prob. For3d.SetMSG ("3D -Nummer 20140420 ist: 127"); Subjekt für 3D.SetMSG ("3D -Nummer 20140421 ist: 333"); }}Ausgangsergebnis:
Observer1 erhält die 3D -Nummer 3D -Nummer -> 20140420's 3D -Nummer: 127, ich möchte sie aufschreiben. Observer2 erhält die 3D -Nummer -> 20140420's 3D -Nummer: 127 Ich möchte meinen Mitbewohnern mitteilen. Observer1 erhält die 3D -Nummer -> 20140421 3D -Nummer: 333, ich möchte sie aufschreiben. Observer2 erhält die 3D -Nummer -> 20140421 3D -Nummer: 333 Ich möchte meinen Mitbewohnern mitteilen.
Es gibt viele Orte in JDK oder Andorid, die den Beobachtermodus implementieren, wie z. B. xxxview.addxxxxlistenter. Natürlich ist xxxview.setonxxxxListener nicht unbedingt ein Beobachtermodus, da der Beobachtermodus eine Eins-zu-Viele-Beziehung ist. Für setxxxListener ist es eine 1-zu-1-Beziehung und sollte als Rückruf bezeichnet werden.
Herzlichen Glückwunsch zum Erlernen des Beobachtermodus. Der obige Beobachtermodus ermöglicht es uns, ihn von Grund auf neu zu schreiben. Natürlich hat Java uns geholfen, den Beobachtermodus mit Hilfe von java.util.observable und java.util.observer implementieren zu können.
Im Folgenden verwenden wir Java-integrierte Klassen, um das Beobachtermuster zu implementieren:
Zunächst gibt es ein 3D -Lotterie -Service -Nummernthema:
Paket com.zhy.pattern.observer.java; Import Java.util.Observable; PUBLIC CLASS Subjekt für 3D erweitert beobachtbar {private String msg; public String getmsg () {return msg; } / ** * Thema Aktualisierungsnachricht * * @param msg * / public void setMSG (String msg) {this.msg = msg; setChanged (); NotifyObServers (); }}Das Folgende ist das Thema einer doppelten Farbball -Servicenummer:
Paket com.zhy.pattern.observer.java; Import Java.util.Observable; Subjektforsq der öffentlichen Klasse erweitert beobachtbar {private String msg; public String getmsg () {return msg; } / ** * Thema Aktualisierungsnachricht * * @param msg * / public void setMSG (String msg) {this.msg = msg; setChanged (); NotifyObServers (); }}Schließlich unsere Benutzer:
Paket com.zhy.pattern.observer.java; Import Java.util.Observable; import Java.util.observer; öffentliche Klasse Observer1 implementiert Observer {public void registersUbject (Observable Observable) {Observable.addobserver (this); } @Override public void update (beobachtbar o, Object arg) {if (o Instance von Prob. System.out.println ("Subjektfor3ds msg ->" + Prob. FOR3D.getmsg ()); } if (oinformof subjektforssq) {subjektforssq Subjektforssq = (Subjektforssq) o; System.out.println ("Subjektforssqs MSG ->" + Subjektforssq.getMsg ()); }}}Schauen Sie sich einen Testcode an:
Paket com.zhy.pattern.observer.java; public class test {public static void main (String [] args) {Prob. FORTIVE 2D = NEW SubjektFor3D (); Subjektforssq Subjektforssq = new Subjektforsssq (); Observer1 Observer1 = neuer Observer1 (); Observer1.RegisterSubject (Subjekt für 3D); Observer1.RegisterSubject (Subjektforssq); Subjekt für 3d.setmsg ("Hallo 3d'nums: 110"); Subjektforssq.setmsg ("ssq'nums: 12,13,31,5,4,3 15"); }}Testergebnisse:
Betreff3ds msg -> Hallo 3D'nums: 110 Betreffforsqs MSG -> SSQ'Nums: 12,13,31,5,4,3 15
Es ist ersichtlich, dass der Code sehr präzise ist, wenn Java-integrierte Klassen zur Implementierung des Observer-Musters verwendet werden. Übrigens, Addobserver, REMEDOBSERVER, NOTIFYOBSERVERS wurden für uns implementiert. Alles, was wir sehen können, ist eine Klasse, keine Schnittstelle. Grundsätzlich hat das Buch eine negative Einstellung zu Javas Design. Es ist der Ansicht, dass Javas integriertes Observer-Muster gegen das Prinzip der interface-orientierten Programmierung verstößt. Wenn Sie jedoch darüber nachdenken, schreiben Sie hier tatsächlich das Beobachtermuster (unsere eigene Implementierung). Die Schnittstellenidee ist sehr gut, aber wenn Sie jetzt weiterhin viele Themen hinzufügen, sind der DDOBServer, REMEDOBSERVER, NOTIFYOBSERVERS für jedes Thema im Grunde genommen gleich. Schnittstellen können keine Wiederverwendung von Code implementieren, und es gibt keine Möglichkeit, den kombinierten Modus zu verwenden, um die Wiederverwendung dieser drei Methoden zu erreichen. Ich denke, es ist vernünftig, diese drei Methoden in der Klasse hier zu implementieren.