Я работаю в месте, где есть несколько проектов.В зависимости от проекта, я хочу, чтобы элементы в списке обрабатывались определенным образом.Я думал, что эта проблема поддается модели Стратегии.Однако, прежде чем полностью перейти к этому шаблону, я создал небольшое приложение, чтобы продемонстрировать, как, по моему мнению, будет работать конечное приложение.
Сначала я создал класс 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)
Я думал, что вы можете динамически назначать только один метод одному экземплярукласс.