Выбор правильного вида для типа объекта - PullRequest
3 голосов
/ 20 ноября 2008

У меня была эта проблема много раз прежде, и у меня никогда не было решения, к которому я чувствовал себя хорошо.

Допустим, у меня есть базовый класс Transaction и два производных класса AdjustmentTransaction и IssueTransaction.

У меня есть список транзакций в пользовательском интерфейсе, и каждая транзакция имеет конкретный тип AdjustmentTransaction или IssueTransaction.

Когда я выбираю транзакцию и нажимаю кнопку «Изменить», мне нужно решить, показывать ли AdjustmentTransactionEditorForm или IssueTransactionEditorForm.

Вопрос в том, как мне сделать это в ОО-режиме, не используя оператор switch для типа выбранной транзакции? Оператор переключения работает, но чувствует себя неуклюже. Мне кажется, что я должен каким-то образом использовать параллельную иерархию наследования между транзакциями и TransactionEditors.

У меня может быть свойство EditorForm в моей транзакции, но это ужасное смешивание моего арахисового масла в пользовательском интерфейсе с моим шоколадом Model.

Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 20 ноября 2008

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

Отношение должно быть указано где-то во внешнем файле. Что-то, что описывает отношения:

Editing AdujustmentTransaction = AdjustmentTransactionEditorForm
Editing IssueTransaction = IssueTransactionEditorForm

При небольшом разборе и более хорошем языке, чем я использовал здесь, этот файл может стать очень обобщенным и многократно используемым - вы можете повторно использовать формы для различных объектов, если требуется, или изменить форму, используемую для редактирования объекта без особых усилий.

(Возможно, вы захотите, чтобы пользователи с именем "Joe" использовали вместо этого "JoeIssueTransactionEditorForm", это довольно легко может быть использовано в вашем "языке")

Это, по сути, внедрение зависимости - вы, вероятно, можете использовать Spring для решения проблемы в более общих чертах.

1 голос
/ 20 ноября 2008

Вам нужно сопоставить вашу «EditorForm» с транзакцией в какой-то момент. У вас есть пара вариантов:

  • Смена заявления ... как и вы, я думаю, что это воняет и плохо масштабируется.
  • Абстрактное свойство "EditorForm" в базовом классе транзакций, оно масштабируется лучше, но имеет плохое разделение проблем.
  • Тип -> Отображатель форм в вашем интерфейсе. Это довольно хорошо масштабируется и сохраняет хорошее разделение.

В C # я бы реализовал отображение типа -> формы следующим образом:

Dictionary <Type,Type> typeMapper = new Dictionary<Type,Type>();
typeMapper.Add(typeof(AdjustTransaction), typeof(AdjustTransactionForm));
// etc, in this example, I'm populating it by hand, 
// in real life, I'd use a key/value pair mapping config file, 
// and populate it at runtime.

затем при нажатии на правку:

Type formToGet;
if (typeMapper.TryGetValue(CurrentTransaction.GetType(), out formToGet))
{
    Form newForm = (Form)Activator.CreateInstance(formToGet);
}
0 голосов
/ 20 ноября 2008

Альтернативой подходу «Словарь / файл конфигурации» будет

1) для определения интерфейса для каждого из редакторов транзакций.

2) В вашей сборке EXE или UI каждая форма должна зарегистрироваться в сборке, которая создает отдельную транзакцию.

3) Класс, контролирующий регистрацию, должен быть одноэлементным, чтобы у вас не было нескольких экземпляров форм, плавающих вокруг.

3) Когда создается отдельная транзакция, она извлекает правильную переменную формы из объекта регистрации и присваивает ей внутреннюю переменную.

4) Когда вызывается метод Edit, он просто использует метод Show внутреннего метода для запуска цепочки вызовов, что приведет к отображению этого редактора транзакций.

Это устраняет необходимость в конфигурационных файлах и словарях. Он продолжает отделять пользовательский интерфейс от объекта. Кроме того, вам не нужно никаких переключателей

Недостатком является необходимость написания интерфейса для каждой формы в дополнение к самой форме.

Если у вас много разных типов редакторов (десятков), тогда в этом случае я рекомендую вам использовать шаблон команд

У вас есть основная команда, в которой содержится диктонарная рекомендация Джонатана. Эти команды по очереди будут использовать этот диктор для выполнения одной из ряда других команд, которые вызывают правильную форму с правильным объектом. Формы продолжают отделяться от самого объекта. Формы находятся в сборке команд. Кроме того, вам не нужно обновлять EXE, чтобы добавить другой редактор только в сборку Command. Наконец, помещая вещи в Command, вы можете гораздо проще реализовать Undo / Redo. (Реализовать неисполнение и выполнение)

0 голосов
/ 20 ноября 2008

Я что-то упускаю в вопросе? Я просто спрашиваю, потому что очевидный ОО ответ будет: Полиморф

Просто запустите Transaction.editWindow () (или как вы хотите его вызывать), и переписать метод в AdjustmentTransaction и IssueTrasaction с требуемым функционалом. Вызов element.editWindow () затем открывает для вас правильный диалог.

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