# SEW-EK, UEB2 Jan R. Borensky, Tim Degold; 5ACHIT, begonnen am 06.04.2021 ## Aufgabe 1 Bei der ersten Aufgaben wurden die entsprechenden `java`-APIs auf die jeweiligen Patterns in den jeweiligen Kategorien (Creational, Structural, Behaviroural) aufgeteilt. [1] Mithilfe einer übersichtlichen Aufzählung von verschiedenen `java`-APIs [5] war es uns möglich folgende Zuordnungen zu treffen: ### Creational **Builder** Hier wird ein Objekt nicht einfach mithilfe eines Konstruktors sondern über eine gewisse Hilfsklasse erstellt, was die Sicherheit sowie die Lesbarkeit verebessert. **Static factory Method** > Examples of this pattern typically involve a factory class that constructs objects of a different type. The objects that are created are usually implementations of an interface. This pattern provides a layer between consumption (the caller) and creation (the factory). [8] **Abstract Factory** Eine *Abstract Factory* soll lt. GOF dafür verwendet werden, um das Erzeugen von verschiedenen Objekten zu ermöglichen, die voneinander abhängig oder zumindest verwandt sind. | Singleton | Builder | Static factory Method | Abstract Factory | | ----------------------------------- | ---------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | java.lang.Runtime, java.awt.Desktop | com.google.common.collect.MapMaker | java.util.Calendar, java.text.NumberFormat, java.nio.charset.Charset | javax.xml.parsers.DocumentBuilderFactory, javax.xml.transform.TransformerFactory, javax.xml.xpath.XPathFactory | ### Structural **Flyweight** hat als Ziel, die Ressourcennutzung der einzelnen Objekte zu minimieren. **Adapter** löst das Problem der inkompatiblen Klassen/APIs. Es dient als Schnittstelle, wleche Information in ein Format bringt, welche von der eigenen Klasse verstanden wird. | Flyweight | Adapter | Decorator | | ------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | java.lang.Integer, java.lang.Boolean | java.io.InputStreamReader, java.io.OutputStreamWriter, java.util.Arrays | java.io.BufferedInputStream, java.io.DataInputStream, java.io.BufferedOutputStream, java.util.zip.ZipOutputStream, java.util.Collections#checkedList() | ### Behavioural **Chain of responsibility** Bei diesem Pattern werden mehrere *behaviors* in einzelne Objekte, sogenannte `handlers` aufgeteilt, die zwischen einem Request und einem Output oÄ eingesetzt werden. Das bedeutet, dass die `handler`, wie in folgendem Beispiel zu sehen ist, gelinked/verknüpft werden: ![](https://i.imgur.com/4grlE3V.png) [9] **Command** Dieses Pattern ermöglicht es, über einige Objekte, die die gleiche Superklasse haben, zu iterieren und eine Funktion aufzurufen, die je nach Objekt unterschiedlich implementiert ist. Dies passiert über eine gemeinsame Methode, welche in der Superklasse definiert und dann von den Subklassen implementiert wird. ![](https://i.imgur.com/hV17cDY.png) **Iterator** stellt die Möglichkeit bereit, über eine Reihe von geordneten Elementen zu "iterieren". **Template Method** stellt die Grundstruktur einer oder mehrerer Methoden in einer (meist abstrkaten) Superklasse zur Verfügung. Die Subklassen nutzen dann diese "Basisimplementierung", um eine abgeänderte Variante derselben Methode bereitzustellen. | Chain of responsibility | Command | Iterator | Strategy | Template method | Observer | | ------------------------ | ------------------------------------------------- | ----------------------------- | ------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | java.servlet.FilterChain *"giving a view into the invocation chain of a filtered request for a resource"* | java.lang.Runnable, java.util.concurrent.Callable | java.util.concurrent.Callable | java.util.Comparator, javax.servlet.Filter | java.util.AbstractList, java.util.AbstractSet, java.util.AbstractMap, java.io.InputStream, java.io.OutputStream, java.io.Reader, java.io.Writer | java.util.EventListener, java.util.Observer/java.util.Observable | <br> ## Aufgabe 2 ### Singleton Pattern Wie oben bereits zu sehen ist, gehört das **Singleton Pattern** zu den *creational patterns*. Bei diesem Pattern soll sichergestellt werden, dass von einer Klasse genau ein Objekt existiert. Das bedeutet, dass hier das gewünschte Objekt meistens einmal erzeugt und dann als statische Instanz abgerufen werden kann. Somit muss nicht nur sichergestellt werden, dass nur ein Objekt dieser Klasse erzeugt wird, sondern, dass dieses auch global verfügbar gemacht wird. [1,2] Auf diesem Bild sieht das UML-Diagramm für ein simples Singleton-Pattern. ![](https://i.imgur.com/bam1WCG.png)[2] Wie man sieht, ist es von außen nicht möglich etwas an dem "Einzelstück" zu verändern. [2] <br> ### Beantwortung - Fragen 1. Der SessionManager ist als Attribut stark mit der Klasse AccessChecker gekoppelt, welche wiederum als Attribut eine ServerConfig hat. Dies macht es sehr schwierig diese Klassen zu testen, da auch die anderen Klassen dafür benötigt werden. Um dieses Problem zu umgehen müsste man die Klassen mocken, was aufgrund des Singleton Patterns nicht so leicht ist, da über Interfaces/Superklassen gearbeitet werden müsste und die `getInstance`-Methode statisch ist und daher nicht überschrieben werden kann. 2. Wir erstellen die Interfaces `IAccessChecker` und `IServerConfig`: ```java public interface IServerConfig { public String getAccessLevel(User u); // ... } public interface IAccessChecker { public boolean mayAccess(User user, String path); // ... } ``` Nun können die konkreten Klassen von diesen Interfaces erben. Danach müssen diese mit `@Singleton` gekennzeichnet werden. Somit wird das Singleton von Guice verwaltet, daher ist auch die `getInstance()` obsolet und kann entfernt werden. Alle Attribute werden somit in den Konstrukor übernomme, welcher wieder für Guice annotiert wird. ```java @Singleton public class AccessChecker implements IAccessChecker { private IServerConfig config; @Inject public AccessChecker(IServerConfig config) { this.config = config; // initialization.. } ... } @Singleton public class ServerConfig implements IServerConfig { ... } ``` Nun wird ein Modul erstellt, wlches die konkreten Klassen an die Interfaces binded. > In Linked bindings, Guice maps a type to its implementation. [Google] Das heißt, dass *binding* dazu verwendet werden kann, die konkrete Implementierung dem Interface zuzuweisen. ```java public class DefaultModule extends AbstractModule { @Override protected void configure() { bind(IAccessChecker.class).to(AccessChecker.class); bind(IServerConfig.class).to(ServerConfig.class); } } ``` Nun können die `getInstance`-Aufrufe in der *SessionManager*-Klasse gelöscht werden, gibt die Attribute als Konstruktor-Parameter angegeben und mit `@Inject` markiert werden: ```java public class SessionManager { private IAccessChecker access; @Inject public SessionManager(IAccessChecker access) { this.access = access; } public Session createSession(User user, String accessedPath) { if (access.mayAccess(user, accessedPath)) { ... } // ... } ``` Um nun eine Instanz der SessionManager-Klasse zu bekommen, wird über Guice-Injector gearbeitet. `Guice.createInjector(new DefaultModule()).getInstance(SessionManager.class)` 3. Nachfolgend wir ein abstraktes Modul verwendet, um zu testen, ob eine neue Session mithilfe des `SessionManager` erstellt werden kann, nachdem hier eine Mock-Klasse (`AccessCheckerMock`) zur als konkrete Implementierung zum Interface `IAccessChecker` mittels `bind` hinzugefügt wurde. ```java public class SessionManagerTest { public static void main(String[] args) { Module module = new AbstractModule() { @Override protected void configure() { bind(IAccessChecker.class).to(AccessCheckerMock.class); } }; SessionManager mgr = Guice.createInjector(module).getInstance(SessionManager.class); User user = new User(); try { mgr.createSession(user, "any path"); assert false; // we should not get here } catch (InsufficientRightsException e) { System.out.println("Success!"); } } } public class AccessCheckerMock implements IAccessChecker { @Override public boolean mayAccess(User user, String path) { return false; } // ... } ``` <br> --- ## Quellen [1] “Dependency Injection with Guice | Object Computing, Inc.” https://objectcomputing.com/resources/publications/sett/may-2007-dependency-injection-with-guice (accessed Apr. 06, 2021). [2] “Google Guice - Linked Bindings - Tutorialspoint.” https://www.tutorialspoint.com/guice/guice_linked_binding.htm (accessed Apr. 06, 2021). [3] “Rheinwerk Computing :: Java ist auch eine Insel - Komponenten, JavaBeans und Module.” https://openbook.rheinwerk-verlag.de/javainsel/13_002.html (accessed Apr. 06, 2021). [4] “Javabeginners - Properties und Binding.” https://javabeginners.de/Frameworks/JavaFX/Properties_und_Binding.php (accessed Apr. 06, 2021). [5] “oop - Examples of GoF Design Patterns in Java’s core libraries - Stack Overflow.” https://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries (accessed Apr. 06, 2021). [6] “Singleton (Entwurfsmuster) – Wikipedia.” https://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster) (accessed Apr. 06, 2021). [7] “Singleton Design Pattern: Das Singleton-Entwurfsmuster kurz erklärt - IONOS.” https://www.ionos.at/digitalguide/websites/web-entwicklung/was-ist-das-singleton-pattern/ (accessed Apr. 06, 2021). [8] “Cleaner Code with Static Factory Methods – Stackify.” https://stackify.com/static-factory-methods/ (accessed Apr. 07, 2021). [9] “Chain of Responsibility.” https://refactoring.guru/design-patterns/chain-of-responsibility (accessed Apr. 07, 2021).