Browse Source

add mediator pattern

MrOzOn 4 years ago
parent
commit
b3fac7673e

+ 24 - 0
src/behavioral_pattern/README.MD

@@ -74,5 +74,29 @@
 - упрощение интерфейса класса агрегата
 - возможность наличия нескольких активных обходов для данного агрегата
 
+# [Посредник (Mediator)](./mediator/main.kt)
+
+Это поведенческий паттерн проектирования, который позволяет уменьшить связанность множества классов между собой, благодаря перемещению этих связей в один класс-посредник.
+
+## Применимость
+
+- существование объектов, связи между которыми сложны и четко определены. Получающиеся при этом взаимозависимости не структурированы и трудны для понимания
+- повторное использование объекта затруднено, поскольку он обменивается информацией со многими другими объектами
+- поведение, распределенное между несколькими классами, должно настраиваться без порождения множества подклассов
+
+## Отношения
+
+Коллеги посылают запросы посреднику и получают запросы от него. Посредник реализует кооперативное поведение путем переадресации каждого запроса подходящему коллеге (или нескольким коллегам)
+
+## Результаты
+
+- снижение числа порождаемых подклассов
+- ослабление связей между коллегами
+- упрощение протоколов взаимодействия объектов
+- абстрагирование способа кооперирования объектов. Выделение механизма посредничества в отдельную концепцию и инкапсуляция ее в одном объекте позволяет сосредоточиться именно на взаимодействии объектов, а не на их индивидуальном поведении
+- централизация управления
+
+
+
 
 

+ 6 - 0
src/behavioral_pattern/mediator/Component.kt

@@ -0,0 +1,6 @@
+package behavioral_pattern.mediator
+
+interface Component {
+    fun setMediator(mediator: Mediator)
+    fun getName(): String
+}

+ 173 - 0
src/behavioral_pattern/mediator/ConcreteComponenets.kt

@@ -0,0 +1,173 @@
+package behavioral_pattern.mediator
+
+import java.awt.event.ActionEvent
+import java.awt.event.KeyEvent
+import javax.swing.*
+
+class AddButton : JButton("Add"), Component {
+
+    private var mediator: Mediator? = null
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    override fun getName(): String = "AddButton"
+
+    override fun fireActionPerformed(event: ActionEvent?) {
+        mediator?.addNewNote(Note())
+    }
+
+}
+
+class DeleteButton : JButton("Del"), Component {
+
+    private var mediator: Mediator? = null
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    override fun getName(): String = "DelButton"
+
+    override fun fireActionPerformed(event: ActionEvent?) {
+        mediator?.deleteNote()
+    }
+
+}
+
+class Filter: JTextField(), Component {
+
+    private var mediator: Mediator? = null
+    private var listModel: ListModel<Note>? = null
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    fun setList(listModel: ListModel<Note>){
+        this.listModel = listModel
+    }
+
+    override fun getName(): String = "Filter"
+
+    override fun processComponentKeyEvent(e: KeyEvent?) {
+        val start = text
+        searchElements(start)
+    }
+
+    private fun searchElements(s: String) {
+        if (listModel==null)
+            return
+        if(s.isEmpty()) {
+            mediator?.setElementsList(listModel!!)
+            return
+        }
+        val notes = mutableListOf<Note>()
+        for (i in 0..listModel!!.size) {
+            notes.add(listModel!!.getElementAt(i))
+        }
+        val listModel = DefaultListModel<Note>()
+        for (note in notes) {
+            if (note.name.contains(s)) {
+                listModel.addElement(note)
+            }
+        }
+        mediator?.setElementsList(listModel)
+    }
+
+}
+
+class List(private val listModel: DefaultListModel<Note>): JList<Note>(listModel), Component {
+
+    private var mediator: Mediator? = null
+
+    init {
+        model = listModel
+        layoutOrientation = VERTICAL
+        val thread = Thread(Hide(this, mediator))
+        thread.start()
+    }
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    override fun getName(): String = "List"
+
+    fun addElement(note: Note) {
+        listModel.addElement(note)
+        val index = listModel.size()-1
+        selectedIndex = index
+        ensureIndexIsVisible(index)
+        mediator?.sendToFilter(listModel)
+    }
+
+    fun deleteElement(){
+        val index = selectedIndex
+        try {
+            listModel.remove(index)
+            mediator?.sendToFilter(listModel)
+        } catch (ex: ArrayIndexOutOfBoundsException) {}
+    }
+
+    fun getCurrentElement(): Note = selectedValue
+
+    class Hide(private val list: List, val mediator: Mediator?): Runnable {
+        override fun run() {
+            while (true) {
+                try {
+                    Thread.sleep(300)
+                } catch (ex: InterruptedException) {
+                    println(ex.printStackTrace())
+                }
+                mediator?.hideElements(list.isSelectionEmpty)
+            }
+        }
+    }
+
+}
+
+class SaveButton: JButton("Save"), Component{
+    private var mediator: Mediator? = null
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    override fun getName(): String = "Save"
+
+    override fun fireActionPerformed(event: ActionEvent?) {
+        mediator?.saveChanges()
+    }
+}
+
+class TextBox: JTextArea(), Component {
+    private var mediator: Mediator? = null
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    override fun getName(): String = "TextBox"
+
+    override fun processComponentKeyEvent(e: KeyEvent?) {
+        mediator?.markNote()
+    }
+
+}
+
+class Title: JTextField(), Component {
+    private var mediator: Mediator? = null
+
+    override fun setMediator(mediator: Mediator) {
+        this.mediator = mediator
+    }
+
+    override fun getName(): String = "Title"
+
+    override fun processComponentKeyEvent(e: KeyEvent?) {
+        mediator?.markNote()
+    }
+
+}

+ 156 - 0
src/behavioral_pattern/mediator/ConcreteMediator.kt

@@ -0,0 +1,156 @@
+package behavioral_pattern.mediator
+
+import java.awt.Color
+import java.awt.Dimension
+import java.awt.FlowLayout
+import java.awt.Font
+import javax.swing.*
+import javax.swing.border.LineBorder
+
+class Editor: Mediator {
+    private var title: Title? = null
+    private var textBox: TextBox? = null
+    private var add: AddButton? = null
+    private var del: DeleteButton? = null
+    private var save: SaveButton? = null
+    private var list: List? = null
+    private var filter: Filter? = null
+
+    private val titleLabel = JLabel("Title:")
+    private val textLabel = JLabel("Text:")
+    private val label = JLabel("Add or select existing note to proceed...")
+
+    override fun registerComponent(component: Component) {
+        component.setMediator(this)
+        when(component.getName()) {
+            "AddButton" -> add = component as AddButton
+            "DelButton" -> del = component as DeleteButton
+            "Filter" -> filter = component as Filter
+            "List" -> {
+                list = component as List
+                list?.addListSelectionListener {
+                    val note = list?.selectedValue
+                    if (note==null) {
+                        clear()
+                    } else {
+                        getInfoFromList(note)
+                    }
+                }
+            }
+            "Save" -> save = component as SaveButton
+            "TextBox" -> textBox = component as TextBox
+            "Title" -> title = component as Title
+        }
+    }
+
+    override fun addNewNote(note: Note) {
+        title?.text = ""
+        textBox?.text = ""
+        list?.addElement(note)
+    }
+
+    override fun deleteNote() {
+        list?.deleteElement()
+    }
+
+    override fun setElementsList(listModel: ListModel<Note>) {
+        list?.model = listModel
+        list?.repaint()
+    }
+
+    override fun sendToFilter(listModel: DefaultListModel<Note>) {
+        filter?.setList(listModel)
+    }
+
+    override fun hideElements(flag: Boolean) {
+        titleLabel.isVisible = flag
+        textLabel.isVisible = flag
+        title?.isVisible = flag
+        textBox?.isVisible = flag
+        save?.isVisible = flag
+        label.isVisible = flag
+    }
+
+    override fun saveChanges() {
+        val note = list?.selectedValue
+        note?.name = title?.text ?: ""
+        note?.text = textBox?.text ?: ""
+        list?.repaint()
+    }
+
+    override fun markNote() {
+        val note = list?.getCurrentElement() ?: return
+        val name = note.name
+        if(!name.endsWith("*"))
+            note.name += "*"
+        list?.repaint()
+    }
+
+    override fun getInfoFromList(note: Note) {
+        title?.text = note.name.replace('*', ' ')
+        textBox?.text = note.text
+    }
+
+    override fun clear() {
+        title?.text = ""
+        textBox?.text = ""
+    }
+
+
+
+    override fun createGUI() {
+        val notes = JFrame("Notes")
+        notes.setSize(960, 600)
+        notes.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
+        val left = JPanel()
+        left.border = LineBorder(Color.BLACK)
+        left.setSize(320, 600)
+        left.layout = BoxLayout(left, BoxLayout.Y_AXIS)
+        val filterPanel = JPanel()
+        filterPanel.add(JLabel("Filter:"))
+        filter?.columns = 20
+        filterPanel.add(filter)
+        filterPanel.preferredSize = Dimension(280, 40)
+        val listPanel = JPanel()
+        list?.fixedCellWidth = 260
+        listPanel.setSize(320, 470)
+        val scrollPane = JScrollPane(list)
+        scrollPane.preferredSize = Dimension(275, 410)
+        listPanel.add(scrollPane)
+        val buttonPanel = JPanel()
+        add?.preferredSize = Dimension(85, 25)
+        buttonPanel.add(add)
+        del?.preferredSize = Dimension(85, 25)
+        buttonPanel.add(del)
+        buttonPanel.layout = FlowLayout()
+        left.add(filterPanel)
+        left.add(listPanel)
+        left.add(buttonPanel)
+        val right = JPanel()
+        right.layout = null
+        right.setSize(640, 600)
+        right.setLocation(320, 0)
+        right.border = LineBorder(Color.BLACK)
+        titleLabel.setBounds(20, 4, 50, 20)
+        title?.setBounds(60, 5, 555, 20)
+        textLabel.setBounds(20, 4, 50, 130)
+        textBox?.border = LineBorder(Color.DARK_GRAY)
+        textBox?.setBounds(20, 80, 595, 410)
+        save?.setBounds(270, 535, 80, 25)
+        label.font = Font("Verdana", Font.PLAIN, 22)
+        label.setBounds(100, 240, 500, 100)
+        right.add(label)
+        right.add(titleLabel)
+        right.add(title)
+        right.add(textLabel)
+        right.add(textBox)
+        right.add(save)
+        notes.layout = null
+        notes.contentPane.add(left)
+        notes.contentPane.add(right)
+        notes.isResizable = false
+        notes.setLocationRelativeTo(null)
+        notes.isVisible = true
+    }
+
+}

+ 18 - 0
src/behavioral_pattern/mediator/Mediator.kt

@@ -0,0 +1,18 @@
+package behavioral_pattern.mediator
+
+import javax.swing.DefaultListModel
+import javax.swing.ListModel
+
+interface Mediator {
+    fun addNewNote(note: Note)
+    fun deleteNote()
+    fun setElementsList(listModel: ListModel<Note>)
+    fun sendToFilter(listModel: DefaultListModel<Note>)
+    fun hideElements(flag: Boolean)
+    fun saveChanges()
+    fun markNote()
+    fun getInfoFromList(note: Note)
+    fun clear()
+    fun registerComponent(component: Component)
+    fun createGUI()
+}

+ 5 - 0
src/behavioral_pattern/mediator/Note.kt

@@ -0,0 +1,5 @@
+package behavioral_pattern.mediator
+
+class Note(var name: String = "New note", var text: String = "") {
+    override fun toString(): String = name
+}

+ 16 - 0
src/behavioral_pattern/mediator/main.kt

@@ -0,0 +1,16 @@
+package behavioral_pattern.mediator
+
+import javax.swing.DefaultListModel
+
+fun main(){
+    val mediator = Editor()
+    mediator.registerComponent(Title())
+    mediator.registerComponent(TextBox())
+    mediator.registerComponent(AddButton())
+    mediator.registerComponent(DeleteButton())
+    mediator.registerComponent(SaveButton())
+    mediator.registerComponent(List(DefaultListModel<Note>()))
+    mediator.registerComponent(Filter())
+
+    mediator.createGUI()
+}