-
Notifications
You must be signed in to change notification settings - Fork 0
Kapitel 8: Entwurfsmuster
Zwei unterschiedliche Entwurfsmuster aus der Vorlesung (oder nach Absprache auch andere) jeweils sinnvoll einsetzen, begründen und UML-Diagramm
Im Rahmen von QuizClash werden vier verschiedene UI-Elemente eingesetzt, welche für eine Darstellung in der CLI (oder auch irgendwo anders) verwendet werden können. Dazu gehören die Folgenden:
- Eingabe von Text (
TextInputScreen
) - Eingabe von Nummern (
NumberInputScreen
) - Auswahl aus einer Liste von Optionen (
OptionScreen
) - Darstellung von reinen Text-Informationen (
InformationScreen
)
Sie erben dabei alle von dem Screen
Basistyp (abstrakte Klasse), sodass alle Subtypen einheitliche Grundfunktionen besitzen.
Um die Application-Schicht von der Darstellung zu entkoppeln, wird das Factory Method Design Pattern eingesetzt, um in der Application-Schicht eine Factory verwenden zu können, um den benötigten Screen
zu erstellen. Dabei ist es für die Application-Schicht nicht von Relevanz, welche konkrete Implementierung des ScreenFactory
Interfaces bei Start der Anwendung in die Application-Schicht gegeben wird. Im Falle der derzeitigen CLI Anwendung besteht eine CLIScreenFactory
Implementierung in der Plugin-Cli-Schicht, welche zusätzlich Implementierungen für die abstrakten Screen-Typen liefert (CLITextInputScreen
, etc.). Bei einer möglichen zukünftigen Änderung der Anforderung an die UI könnten neue Implementierungen für die ScreenFactory
und die abstrakten Screen-Typen geliefert werden, eine Änderung in der Application-Schicht wäre nicht notwendig.
classDiagram
direction BT
class CLIInformationScreen {
+ CLIInformationScreen(String, List~String~, boolean, CLIWindowManager)
+ CLIInformationScreen(String, List~String~, CLIWindowManager)
~ CLIWindowManager cliWindow
+ render() void
}
class CLINumberInputScreen {
+ CLINumberInputScreen(String, String, CLIWindowManager)
- CLIWindowManager cliWindow
- int userInput
+ render() void
+ getNumberInput() Action~Integer~
}
class CLIOptionScreen {
+ CLIOptionScreen(String, List~Displayable~, CLIWindowManager)
- CLIWindowManager cliWindow
- int userOption
- selectFromOptions(List~Displayable~) int
+ render() void
+ getOptionInput() Action~Integer~
}
class CLIScreenFactory {
+ CLIScreenFactory(CLIWindowManager)
~ CLIWindowManager cliWindow
+ createNumberInputScreen(String, String) NumberInputScreen
+ createOptionScreen(String, List~Displayable~) OptionScreen
+ createInformationScreen(String, List~String~, boolean) InformationScreen
+ createTextInputScreen(String, String) TextInputScreen
+ createInformationScreen(String, List~String~) InformationScreen
}
class CLITextInputScreen {
+ CLITextInputScreen(String, String, CLIWindowManager)
- CLIWindowManager cliWindow
- String userInput
+ render() void
+ getTextInput() Action~String~
}
class InformationScreen {
+ InformationScreen(String, List~String~)
+ InformationScreen(String, List~String~, boolean)
- List~String~ lines
- boolean isBlocking
+ getLines() List~String~
+ isBlocking() boolean
}
class NumberInputScreen {
+ NumberInputScreen(String, String)
- String inputRequest
+ getNumberInput() Action~Integer~
+ getInputRequest() String
}
class OptionScreen {
+ OptionScreen(String, List~Displayable~)
- List~Displayable~ displayableList
+ getScreenOptions() List~Displayable~
+ getOptionInput() Action~Integer~
}
class Screen {
+ Screen(String)
- String screenName
+ getScreenName() String
+ render() void
}
class ScreenFactory {
<<Interface>>
+ createTextInputScreen(String, String) TextInputScreen
+ createInformationScreen(String, List~String~) InformationScreen
+ createInformationScreen(String, List~String~, boolean) InformationScreen
+ createNumberInputScreen(String, String) NumberInputScreen
+ createOptionScreen(String, List~Displayable~) OptionScreen
}
class TextInputScreen {
+ TextInputScreen(String, String)
- String inputRequest
+ getTextInput() Action~String~
+ getInputRequest() String
}
CLIInformationScreen --> InformationScreen
CLINumberInputScreen --> NumberInputScreen
CLIOptionScreen --> OptionScreen
CLIScreenFactory ..> CLIInformationScreen : «create»
CLIScreenFactory ..> CLINumberInputScreen : «create»
CLIScreenFactory ..> CLIOptionScreen : «create»
CLIScreenFactory ..> CLITextInputScreen : «create»
CLIScreenFactory ..> ScreenFactory
CLITextInputScreen --> TextInputScreen
InformationScreen --> Screen
NumberInputScreen --> Screen
OptionScreen --> Screen
TextInputScreen --> Screen
Im Rahmen des JSON-Parsings der Spiel-Kategorien (inklusive Fragen und Antwortmöglichkeiten) wird das Builder Pattern verwendet, um Elemente vom Typ Category
, Question
und QuestionOption
zu erstellen. Dazu sind die Klassen CategoryBuilder
, QuestionBuilder
und QuestionOptionBuilder
vorhanden. Da in dem JSON die einzelnen Elemente ineinander verschachtelt sind (Fragen haben feste Antwortmöglichkeiten und sind einer Kategorie fest zugeordnet), können diese nicht in einem Schritt erstellt werden. Um die Entwicklung daher besser zu strukturieren, wurde das Builder Pattern eingesetzt.
classDiagram
direction BT
class Category {
+ Category(int, String, Question[])
- int id
- String categoryName
- Question[] questions
+ getDisplayName() String
+ getQuestions() Question[]
+ getCategoryName() String
+ getRandomQuestion() Question
+ getId() int
}
class CategoryBuilder {
+ CategoryBuilder()
- int id
- String categoryName
- List~Question~ questions
+ setId(int) CategoryBuilder
+ addQuestion(Question) CategoryBuilder
+ build() Category
+ setCategoryName(String) CategoryBuilder
}
class JSONCategoryParser {
+ JSONCategoryParser()
- parseCategory(JSONObject, boolean) Category
- parseQuestionOption(JSONObject) QuestionOption
+ parseFromJSONArray(JSONArray, boolean) Category[]
- parseQuestion(JSONObject, boolean) Question
}
class Question {
+ Question(int, String, QuestionOption[], boolean)
+ Question(int, String, QuestionOption[])
- int id
- String question
- QuestionOption[] questionOptions
+ checkAnswer(int) boolean
+ getQuestion() String
+ getId() int
+ getQuestionOptions() QuestionOption[]
}
class QuestionBuilder {
+ QuestionBuilder()
- String question
- List~QuestionOption~ questionOptions
- int id
- boolean shuffle
+ setQuestion(String) QuestionBuilder
+ build() Question
+ setQuestionShuffling(boolean) QuestionBuilder
+ setId(int) QuestionBuilder
+ addQuestionOption(QuestionOption) QuestionBuilder
}
class QuestionOption {
+ QuestionOption(String, boolean)
- boolean isRight
- String questionOption
+ getDisplayName() String
+ isRight() boolean
+ getQuestionOption() String
}
class QuestionOptionBuilder {
+ QuestionOptionBuilder()
- String questionOption
- boolean isRight
+ build() QuestionOption
+ setQuestionOption(String) QuestionOptionBuilder
+ setIsRight(boolean) QuestionOptionBuilder
}
Category "1" *--> "questions *" Question
CategoryBuilder ..> Category : «create»
CategoryBuilder ..> Question : «create»
CategoryBuilder "1" *--> "questions *" Question
JSONCategoryParser ..> Category : «create»
JSONCategoryParser ..> CategoryBuilder : «create»
JSONCategoryParser ..> QuestionBuilder : «create»
JSONCategoryParser ..> QuestionOptionBuilder : «create»
Question "1" *--> "questionOptions *" QuestionOption
Question ..> QuestionOption : «create»
QuestionBuilder ..> Question : «create»
QuestionBuilder "1" *--> "questionOptions *" QuestionOption
QuestionBuilder ..> QuestionOption : «create»
QuestionOptionBuilder ..> QuestionOption : «create»