{"id":371,"date":"2024-05-02T18:22:27","date_gmt":"2024-05-02T17:22:27","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=371"},"modified":"2024-06-03T18:23:47","modified_gmt":"2024-06-03T17:23:47","slug":"das-listener-design-pattern-in-java","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=371","title":{"rendered":"Das Listener-Design-Pattern in Java"},"content":{"rendered":"\n<p>Das Listener-Design-Pattern ist ein weit verbreitetes Entwurfsmuster in der Softwareentwicklung, insbesondere in der Programmiersprache Java. Es erm\u00f6glicht die Implementierung von Ereignisverwaltungssystemen, bei denen eine Komponente (der \u201eSender\u201c oder \u201eSubjekt\u201c) Ereignisse erzeugt, die von einer oder mehreren anderen Komponenten (den \u201eListenern\u201c oder \u201eBeobachtern\u201c) verarbeitet werden.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Grundlagen des Listener-Design-Patterns<\/h4>\n\n\n\n<p>Das Listener-Design-Pattern geh\u00f6rt zur Familie der Verhaltensmuster und \u00e4hnelt dem Observer-Pattern. Der Hauptunterschied besteht darin, dass das Listener-Pattern stark typisiert ist und \u00fcblicherweise in GUI-Anwendungen verwendet wird, w\u00e4hrend das Observer-Pattern allgemeiner und in verschiedenen Anwendungsbereichen eingesetzt wird.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Komponenten des Patterns<\/h5>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Sender (Subjekt)<\/strong>: Dies ist die Komponente, die Ereignisse erzeugt. In Java-GUI-Frameworks wie Swing oder AWT sind dies typischerweise Benutzeroberfl\u00e4chenkomponenten wie Schaltfl\u00e4chen oder Textfelder.<\/li>\n\n\n\n<li><strong>Listener (Beobachter)<\/strong>: Dies sind Objekte, die Ereignisse empfangen und darauf reagieren. Listener implementieren spezielle Schnittstellen, die Methoden zur Ereignisbehandlung definieren.<\/li>\n\n\n\n<li><strong>Ereignisse<\/strong>: Ereignisse sind spezielle Objekte, die Informationen \u00fcber das aufgetretene Ereignis enthalten. Beispielsweise kann ein Mausklick-Ereignis Informationen \u00fcber die Position des Klicks und die gedr\u00fcckte Maustaste enthalten.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Implementierung in Java<\/h4>\n\n\n\n<p>Die Implementierung des Listener-Patterns in Java erfolgt typischerweise durch die Verwendung von Schnittstellen und die Registrierung von Listenern beim Sender. Hier ist ein einfaches Beispiel, das eine Schaltfl\u00e4che und einen ActionListener verwendet, um auf einen Mausklick zu reagieren.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Schritt 1: Definieren der Listener-Schnittstelle<\/h5>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">ActionListener<\/span> <\/span>{\n    void actionPerformed(ActionEvent e);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h5 class=\"wp-block-heading\">Schritt 2: Erstellen des Ereignisobjekts<\/h5>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">public <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ActionEvent<\/span> <\/span>{\n    private <span class=\"hljs-built_in\">Object<\/span> source;\n\n    public ActionEvent(<span class=\"hljs-built_in\">Object<\/span> source) {\n        <span class=\"hljs-keyword\">this<\/span>.source = source;\n    }\n\n    public <span class=\"hljs-built_in\">Object<\/span> getSource() {\n        <span class=\"hljs-keyword\">return<\/span> source;\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h5 class=\"wp-block-heading\">Schritt 3: Implementieren des Senders<\/h5>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">import java.util.ArrayList;\nimport java.util.<span class=\"hljs-keyword\">List<\/span>;\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Button<\/span> <\/span>{\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">List<\/span>&lt;ActionListener&gt; listeners = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;();\n\n    <span class=\"hljs-keyword\">public<\/span> void addActionListener(ActionListener listener) {\n        listeners.add(listener);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> void click() {\n        ActionEvent event = <span class=\"hljs-keyword\">new<\/span> ActionEvent(this);\n        <span class=\"hljs-keyword\">for<\/span> (ActionListener listener : listeners) {\n            listener.actionPerformed(event);\n        }\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h5 class=\"wp-block-heading\">Schritt 4: Implementieren des Listeners<\/h5>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ButtonClickListener<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">ActionListener<\/span> <\/span>{\n    @Override\n    <span class=\"hljs-keyword\">public<\/span> void actionPerformed(ActionEvent e) {\n        System.out.println(<span class=\"hljs-string\">\"Button was clicked!\"<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h5 class=\"wp-block-heading\">Schritt 5: Verwendung des Patterns<\/h5>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">public <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Main<\/span> <\/span>{\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) {\n        Button button = <span class=\"hljs-keyword\">new<\/span> Button();\n        button.addActionListener(<span class=\"hljs-keyword\">new<\/span> ButtonClickListener());\n\n        <span class=\"hljs-comment\">\/\/ Simuliere einen Klick auf den Button<\/span>\n        button.click();\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel sehen wir eine einfache Implementierung des Listener-Patterns. Die <code>Button<\/code>-Klasse ist der Sender, der eine Liste von <code>ActionListener<\/code>-Objekten verwaltet und ein <code>ActionEvent<\/code> erzeugt, wenn die <code>click<\/code>-Methode aufgerufen wird. Der <code>ButtonClickListener<\/code> implementiert die <code>ActionListener<\/code>-Schnittstelle und definiert, was passieren soll, wenn das Ereignis auftritt.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Praktische Anwendungen<\/h4>\n\n\n\n<p>Das Listener-Design-Pattern wird h\u00e4ufig in GUI-Frameworks verwendet, aber seine Anwendungsm\u00f6glichkeiten sind nicht darauf beschr\u00e4nkt. Es kann in jeder Situation verwendet werden, in der ein Objekt mehrere andere Objekte \u00fcber Zustands\u00e4nderungen oder Ereignisse informieren muss.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Verwendung in Swing<\/h5>\n\n\n\n<p>In Java Swing wird das Listener-Pattern ausgiebig verwendet. Hier ist ein Beispiel, das zeigt, wie ein <code>JButton<\/code> mit einem <code>ActionListener<\/code> verwendet wird:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> javax.swing.*;\n<span class=\"hljs-keyword\">import<\/span> java.awt.event.ActionEvent;\n<span class=\"hljs-keyword\">import<\/span> java.awt.event.ActionListener;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SwingExample<\/span> <\/span>{\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) {\n        JFrame frame = <span class=\"hljs-keyword\">new<\/span> JFrame(<span class=\"hljs-string\">\"Button Example\"<\/span>);\n        JButton button = <span class=\"hljs-keyword\">new<\/span> JButton(<span class=\"hljs-string\">\"Click Me\"<\/span>);\n\n        button.addActionListener(<span class=\"hljs-keyword\">new<\/span> ActionListener() {\n            @Override\n            public <span class=\"hljs-keyword\">void<\/span> actionPerformed(ActionEvent e) {\n                System.out.println(<span class=\"hljs-string\">\"Button was clicked!\"<\/span>);\n            }\n        });\n\n        frame.add(button);\n        frame.setSize(<span class=\"hljs-number\">200<\/span>, <span class=\"hljs-number\">200<\/span>);\n        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n        frame.setVisible(<span class=\"hljs-literal\">true<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel erstellt der Code ein <code>JFrame<\/code> mit einem <code>JButton<\/code>. Ein <code>ActionListener<\/code> wird dem Button hinzugef\u00fcgt, der eine Nachricht auf der Konsole ausgibt, wenn der Button geklickt wird.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Listener-Pattern in Multithreading-Umgebungen<\/h5>\n\n\n\n<p>Ein weiterer wichtiger Anwendungsfall des Listener-Patterns ist in Multithreading-Umgebungen. Hier kann das Pattern verwendet werden, um Ereignisse zwischen verschiedenen Threads zu koordinieren. Ein Beispiel w\u00e4re ein Server, der auf Verbindungen wartet und mehrere Clients \u00fcber neue Verbindungen informiert.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">import java.util.concurrent.CopyOnWriteArrayList;\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Server<\/span> <\/span>{\n    <span class=\"hljs-keyword\">private<\/span> CopyOnWriteArrayList&lt;ConnectionListener&gt; listeners = <span class=\"hljs-keyword\">new<\/span> CopyOnWriteArrayList&lt;&gt;();\n\n    <span class=\"hljs-keyword\">public<\/span> void addConnectionListener(ConnectionListener listener) {\n        listeners.add(listener);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> void newConnection() {\n        ConnectionEvent event = <span class=\"hljs-keyword\">new<\/span> ConnectionEvent(this);\n        <span class=\"hljs-keyword\">for<\/span> (ConnectionListener listener : listeners) {\n            listener.connectionEstablished(event);\n        }\n    }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">ConnectionListener<\/span> <\/span>{\n    void connectionEstablished(ConnectionEvent e);\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ConnectionEvent<\/span> <\/span>{\n    <span class=\"hljs-keyword\">private<\/span> Object source;\n\n    <span class=\"hljs-keyword\">public<\/span> ConnectionEvent(Object source) {\n        this.source = source;\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> Object getSource() {\n        <span class=\"hljs-keyword\">return<\/span> source;\n    }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ClientHandler<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">ConnectionListener<\/span> <\/span>{\n    @Override\n    <span class=\"hljs-keyword\">public<\/span> void connectionEstablished(ConnectionEvent e) {\n        System.out.println(<span class=\"hljs-string\">\"New connection established!\"<\/span>);\n    }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Main<\/span> <\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> void main(String&#91;] args) {\n        Server server = <span class=\"hljs-keyword\">new<\/span> Server();\n        server.addConnectionListener(<span class=\"hljs-keyword\">new<\/span> ClientHandler());\n\n        <span class=\"hljs-comment\">\/\/ Simuliere eine neue Verbindung<\/span>\n        server.newConnection();\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird das Listener-Pattern verwendet, um Clients \u00fcber neue Verbindungen zu informieren. Das <code>CopyOnWriteArrayList<\/code> wird verwendet, um Thread-Sicherheit zu gew\u00e4hrleisten.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Vorteile des Listener-Design-Patterns<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Entkopplung<\/strong>: Das Pattern entkoppelt den Sender vom Empf\u00e4nger. Der Sender muss nichts \u00fcber die spezifischen Implementierungen der Listener wissen, was die Flexibilit\u00e4t und Wiederverwendbarkeit des Codes erh\u00f6ht.<\/li>\n\n\n\n<li><strong>Erweiterbarkeit<\/strong>: Neue Listener k\u00f6nnen leicht hinzugef\u00fcgt werden, ohne den bestehenden Code zu \u00e4ndern.<\/li>\n\n\n\n<li><strong>Verteilung von Ereignissen<\/strong>: Es erm\u00f6glicht die Verteilung von Ereignissen an mehrere Empf\u00e4nger, was besonders in GUIs und verteilten Systemen n\u00fctzlich ist.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Nachteile des Listener-Design-Patterns<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Komplexit\u00e4t<\/strong>: Die Verwaltung von Listenern kann komplex werden, insbesondere wenn viele verschiedene Ereignistypen und Listener beteiligt sind.<\/li>\n\n\n\n<li><strong>Leistungsprobleme<\/strong>: In Anwendungen mit einer gro\u00dfen Anzahl von Listenern kann die Leistung beeintr\u00e4chtigt werden, da jeder Listener benachrichtigt werden muss.<\/li>\n\n\n\n<li><strong>Ged\u00e4chtnisleckrisiko<\/strong>: Wenn Listener nicht ordnungsgem\u00e4\u00df entfernt werden, kann dies zu Speicherlecks f\u00fchren.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Fazit<\/h4>\n\n\n\n<p>Das Listener-Design-Pattern ist ein leistungsf\u00e4higes Werkzeug f\u00fcr die Entwicklung ereignisgesteuerter Anwendungen in Java. Es f\u00f6rdert die Entkopplung von Komponenten, erm\u00f6glicht eine einfache Erweiterung und unterst\u00fctzt die Verteilung von Ereignissen. Trotz seiner Komplexit\u00e4t und der potenziellen Leistungsprobleme bietet es eine solide Grundlage f\u00fcr die Implementierung reaktiver Systeme und ist ein integraler Bestandteil moderner Java-Anwendungen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Das Listener-Design-Pattern ist ein weit verbreitetes Entwurfsmuster in der Softwareentwicklung, insbesondere in der Programmiersprache Java. Es erm\u00f6glicht die Implementierung von Ereignisverwaltungssystemen, bei denen eine Komponente (der \u201eSender\u201c oder \u201eSubjekt\u201c) Ereignisse erzeugt, die von einer oder mehreren anderen Komponenten (den \u201eListenern\u201c oder \u201eBeobachtern\u201c) verarbeitet werden. Grundlagen des Listener-Design-Patterns Das Listener-Design-Pattern geh\u00f6rt zur Familie der Verhaltensmuster und [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-371","post","type-post","status-publish","format-standard","hentry","category-plain_java"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/371","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=371"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/371\/revisions"}],"predecessor-version":[{"id":372,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/371\/revisions\/372"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=371"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=371"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}