Использование шаблона проектирования стратегии с Python - PullRequest
0 голосов
/ 08 ноября 2018

Я работаю в месте, где есть несколько проектов.В зависимости от проекта, я хочу, чтобы элементы в списке обрабатывались определенным образом.Я думал, что эта проблема поддается модели Стратегии.Однако, прежде чем полностью перейти к этому шаблону, я создал небольшое приложение, чтобы продемонстрировать, как, по моему мнению, будет работать конечное приложение.

Сначала я создал класс Strategy:

import types
import rules.work_on_x

class WorkOnProjectsStrategy:

    def __init__(self, project="default"):
        self.project = project
        self.msg = "{0} is the project.".format(self.project)

        if project == "x":
            self.do_that = types.MethodType(rules.work_on_x.do_that, self)
            self.do_this = types.MethodType(rules.work_on_x.do_this, self)

    def do_that(self):
        print("Do that!")

    def do_this(self):
        print("Do this!")

Как вы видите, у меня есть несколько определенных мной методов, которые приводят к тому, что методы do_that и do_this ведут себя определенным образом с проектом под названиемx.

def do_that(self, thing):
    print(self.msg)
    print("Doing that on {0}".format(thing))

def do_this(self, some_thing):
    print(self.msg)
    print("Doing this on {0}".format(some_thing))

Затем я создал клиент (простой графический интерфейс), который будет использовать класс стратегии.

import os
import sys

from work_on_projects_strategy import WorkOnProjectsStrategy

from PySide2 import QtCore
from PySide2 import QtUiTools
from PySide2 import QtWidgets

class Client(QtWidgets.QWidget):

    def __init__(self, ui_file, parent=None):
        super().__init__(parent)

        # Load the ui file
        ui_file = QtCore.QFile(ui_file)
        ui_file.open(QtCore.QFile.ReadOnly)
        loader = QtUiTools.QUiLoader()
        self.my_widget = loader.load(ui_file)
        ui_file.close()
        self.my_widget.show()

        # Set up connections
        self.line_edit_input_asset = \
            self.my_widget.findChild(QtCore.QObject, "lineEdit_inputasset")
        self.push_button_execute = \
            self.my_widget.findChild(QtCore.QObject, "pushButton_execute")
        self.push_button_execute.clicked.connect(self.doing_stuff)

    def doing_stuff(self):
        proj = self.line_edit_input_asset.displayText()
        things = ["thing_1", "thing_2"]
        for thing in things:
            strategy = WorkOnProjectsStrategy(proj)
            if thing == "thing_1":
                strategy.do_that(thing)
            elif thing == "thing_2":
                strategy.do_this(thing)

def main():
    app = QtWidgets.QApplication()
    client_ui = os.path.join("ui", "demo_client.ui")
    client_tool = Client(client_ui)
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Можно ли улучшить этот дизайн?Я заметил, что одна проблема заключается в том, что я могу закончить с большим оператором if / else в классе Strategy.Это может быть легко понять, но я не уверен, что это особенно элегантно.Код работает.Вот вывод после ввода «x» в GUI:

(MY_ENV) > python .\client.py
x is the project.
Doing that on thing_1
x is the project.
Doing this on thing_2

Я удивлен, что это сработало.

if project == "x":
    self.do_that = types.MethodType(rules.work_on_x.do_that, self)
    self.do_this = types.MethodType(rules.work_on_x.do_this, self)

Я думал, что вы можете динамически назначать только один метод одному экземплярукласс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...