Python デザインパターン サンプルコード Mediator
Mark Summerfield『実践 Python 3』デザインパターンのサンプルコード
Python3(3.11)で動くソースコード(.pyファイル .ipynbファイル)あります
「anaconda3」on .py「PyCharm」.ipynb「Jupyter Notebook」
(2023-11-17)Python3.11で動作確認済み
Mediator Medeated (on_change) (on_change) ↑ ↑ Button Text (click, __str__) (text, __str__) Form (creat_widgets, create_mediator, update_ui, clicked)【mediator2.py】【mediator2d.py】
Medeated (on_change) ↑ ↑ Button Text (click, __str__) (text, __str__) Form (creat_widgets, create_mediator, _update_ui_mediator, _clicked_mediator)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
#!/usr/bin/env python3 # Copyright c 2012-13 Qtrac Ltd. All rights reserved. # This program or module is free software: you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. It is provided for # educational purposes and is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. import collections def main(): form = Form() test_user_interaction_with(form) class Form: def __init__(self): self.create_widgets() self.create_mediator() def create_widgets(self): self.nameText = Text() self.emailText = Text() self.okButton = Button("OK") self.cancelButton = Button("Cancel") def create_mediator(self): self.mediator = Mediator(((self.nameText, self.update_ui), (self.emailText, self.update_ui), (self.okButton, self.clicked), (self.cancelButton, self.clicked))) self.update_ui() def update_ui(self, widget=None): self.okButton.enabled = (bool(self.nameText.text) and bool(self.emailText.text)) def clicked(self, widget): if widget == self.okButton: print("OK") elif widget == self.cancelButton: print("Cancel") class Mediator: def __init__(self, widgetCallablePairs): self.callablesForWidget = collections.defaultdict(list) for widget, caller in widgetCallablePairs: self.callablesForWidget[widget].append(caller) widget.mediator = self def on_change(self, widget): callables = self.callablesForWidget.get(widget) if callables is not None: for caller in callables: caller(widget) else: raise AttributeError("No on_change() method registered for {}" .format(widget)) class Mediated: def __init__(self): self.mediator = None def on_change(self): if self.mediator is not None: self.mediator.on_change(self) class Button(Mediated): def __init__(self, text=""): super().__init__() self.enabled = True self.text = text def click(self): if self.enabled: self.on_change() def __str__(self): return "Button({!r}) {}".format(self.text, "enabled" if self.enabled else "disabled") class Text(Mediated): def __init__(self, text=""): super().__init__() self.__text = text @property def text(self): return self.__text @text.setter def text(self, text): if self.text != text: self.__text = text self.on_change() def __str__(self): return "Text({!r})".format(self.text) def test_user_interaction_with(form): form.okButton.click() # Ignored because it is disabled print(form.okButton.enabled) # False form.nameText.text = "Fred" print(form.okButton.enabled) # False form.emailText.text = "fred@bloggers.com" print(form.okButton.enabled) # True form.okButton.click() # OK form.emailText.text = "" print(form.okButton.enabled) # False form.cancelButton.click() # Cancel if __name__ == "__main__": main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
#!/usr/bin/env python3 # Copyright c 2012-13 Qtrac Ltd. All rights reserved. # This program or module is free software: you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. It is provided for # educational purposes and is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. import collections def main(): form = Form() test_user_interaction_with(form) class Form: def __init__(self): self.create_widgets() self.create_mediator() def create_widgets(self): self.nameText = Text() self.emailText = Text() self.okButton = Button("OK") self.cancelButton = Button("Cancel") def create_mediator(self): self.mediator = Mediator(((self.nameText, self.update_ui), (self.emailText, self.update_ui), (self.okButton, self.clicked), (self.cancelButton, self.clicked))) self.update_ui() def update_ui(self, widget=None): self.okButton.enabled = (bool(self.nameText.text) and bool(self.emailText.text)) def clicked(self, widget): if widget == self.okButton: print("OK") elif widget == self.cancelButton: print("Cancel") class Mediator: def __init__(self, widgetCallablePairs): self.callablesForWidget = collections.defaultdict(list) for widget, caller in widgetCallablePairs: self.callablesForWidget[widget].append(caller) widget.mediator = self def on_change(self, widget): callables = self.callablesForWidget.get(widget) if callables is not None: for caller in callables: caller(widget) else: raise AttributeError("No on_change() method registered for {}" .format(widget)) def mediated(Class): setattr(Class, "mediator", None) def on_change(self): if self.mediator is not None: self.mediator.on_change(self) setattr(Class, "on_change", on_change) return Class @mediated class Button: def __init__(self, text=""): super().__init__() self.enabled = True self.text = text def click(self): if self.enabled: self.on_change() def __str__(self): return "Button({!r}) {}".format(self.text, "enabled" if self.enabled else "disabled") @mediated class Text: def __init__(self, text=""): super().__init__() self.__text = text @property def text(self): return self.__text @text.setter def text(self, text): if self.text != text: self.__text = text self.on_change() def __str__(self): return "Text({!r})".format(self.text) def test_user_interaction_with(form): form.okButton.click() # Ignored because it is disabled print(form.okButton.enabled) # False form.nameText.text = "Fred" print(form.okButton.enabled) # False form.emailText.text = "fred@bloggers.com" print(form.okButton.enabled) # True form.okButton.click() # OK form.emailText.text = "" print(form.okButton.enabled) # False form.cancelButton.click() # Cancel if __name__ == "__main__": main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
#!/usr/bin/env python3 # Copyright c 2012-13 Qtrac Ltd. All rights reserved. # This program or module is free software: you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. It is provided for # educational purposes and is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. from Qtrac import coroutine def main(): form = Form() test_user_interaction_with(form) class Form: def __init__(self): self.create_widgets() self.create_mediator() def create_widgets(self): self.nameText = Text() self.emailText = Text() self.okButton = Button("OK") self.cancelButton = Button("Cancel") def create_mediator(self): self.mediator = self._update_ui_mediator(self._clicked_mediator()) for widget in (self.nameText, self.emailText, self.okButton, self.cancelButton): widget.mediator = self.mediator self.mediator.send(None) @coroutine def _update_ui_mediator(self, successor=None): while True: widget = (yield) self.okButton.enabled = (bool(self.nameText.text) and bool(self.emailText.text)) if successor is not None: successor.send(widget) @coroutine def _clicked_mediator(self, successor=None): while True: widget = (yield) if widget == self.okButton: print("OK") elif widget == self.cancelButton: print("Cancel") elif successor is not None: successor.send(widget) class Mediated: def __init__(self): self.mediator = None def on_change(self): if self.mediator is not None: self.mediator.send(self) class Button(Mediated): def __init__(self, text=""): super().__init__() self.enabled = True self.text = text def click(self): if self.enabled: self.on_change() def __str__(self): return "Button({!r}) {}".format(self.text, "enabled" if self.enabled else "disabled") class Text(Mediated): def __init__(self, text=""): super().__init__() self.__text = text @property def text(self): return self.__text @text.setter def text(self, text): if self.text != text: self.__text = text self.on_change() def __str__(self): return "Text({!r})".format(self.text) def test_user_interaction_with(form): form.okButton.click() # Ignored because it is disabled print(form.okButton.enabled) # False form.nameText.text = "Fred" print(form.okButton.enabled) # False form.emailText.text = "fred@bloggers.com" print(form.okButton.enabled) # True form.okButton.click() # OK form.emailText.text = "" print(form.okButton.enabled) # False form.cancelButton.click() # Cancel if __name__ == "__main__": main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
#!/usr/bin/env python3 # Copyright c 2012-13 Qtrac Ltd. All rights reserved. # This program or module is free software: you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. It is provided for # educational purposes and is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. from Qtrac import coroutine def main(): form = Form() test_user_interaction_with(form) class Form: def __init__(self): self.create_widgets() self.create_mediator() def create_widgets(self): self.nameText = Text() self.emailText = Text() self.okButton = Button("OK") self.cancelButton = Button("Cancel") def create_mediator(self): self.mediator = self._update_ui_mediator(self._clicked_mediator()) for widget in (self.nameText, self.emailText, self.okButton, self.cancelButton): widget.mediator = self.mediator self.mediator.send(None) @coroutine def _update_ui_mediator(self, successor=None): while True: widget = (yield) self.okButton.enabled = (bool(self.nameText.text) and bool(self.emailText.text)) if successor is not None: successor.send(widget) @coroutine def _clicked_mediator(self, successor=None): while True: widget = (yield) if widget == self.okButton: print("OK") elif widget == self.cancelButton: print("Cancel") elif successor is not None: successor.send(widget) def mediated(Class): setattr(Class, "mediator", None) def on_change(self): if self.mediator is not None: self.mediator.send(self) setattr(Class, "on_change", on_change) return Class @mediated class Button: def __init__(self, text=""): super().__init__() self.enabled = True self.text = text def click(self): if self.enabled: self.on_change() def __str__(self): return "Button({!r}) {}".format(self.text, "enabled" if self.enabled else "disabled") @mediated class Text: def __init__(self, text=""): super().__init__() self.__text = text @property def text(self): return self.__text @text.setter def text(self, text): if self.text != text: self.__text = text self.on_change() def __str__(self): return "Text({!r})".format(self.text) def test_user_interaction_with(form): form.okButton.click() # Ignored because it is disabled print(form.okButton.enabled) # False form.nameText.text = "Fred" print(form.okButton.enabled) # False form.emailText.text = "fred@bloggers.com" print(form.okButton.enabled) # True form.okButton.click() # OK form.emailText.text = "" print(form.okButton.enabled) # False form.cancelButton.click() # Cancel if __name__ == "__main__": main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#!/usr/bin/env python3 # Copyright c 2012-13 Qtrac Ltd. All rights reserved. # This program or module is free software: you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. It is provided for # educational purposes and is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. import abc import collections import errno import functools import os import sys def coroutine(function): @functools.wraps(function) def wrapper(*args, **kwargs): generator = function(*args, **kwargs) next(generator) return generator return wrapper