Глобально доступное хранилище данных в управляемой меню программе? - PullRequest
2 голосов
/ 13 января 2011

Я новичок в Stack Overflow, но я ищу некоторые из лучших программных решений на этом сайте. Итак, у меня есть вопрос, чтобы спросить.

Я пишу программу на Delphi, которая является программой на основе меню TUI для локального бизнес-клиента. Они попросили меня сохранить пользовательский интерфейс таким же, как в старой программе (написанной на BASIC для MS-DOS, 1982 г.), поэтому все меню управляется глобальными данными, которые хранятся в файлах и перезагружаются программой. Каждое подменю представляет собой программу, которая сама по себе запускается активным меню (также программой).

Я написал свою собственную структуру TUI и менеджер UI для отображения меню и подменю. Диспетчер пользовательского интерфейса содержит переопределенный метод «Draw» для отображения меню и другой переопределенный метод «OnEvent», который обрабатывает события клавиатуры в пользовательском интерфейсе. Мой первый вопрос: считаете ли вы, что это подходящий метод для создания управляемой меню программы, содержащей подменю? Пример того, как это работает:

type
  TMenu1 = class(TExtendedUIManager)
  private
    procedure OnEvent (c: Char); override;
  end;

type
  TSubMenu1 = class(TExtendedUIManager)
  end;

procedure TMenu1.OnEvent (c: Char);
var
  Next: TExtendedUIManager;
begin
  if c = '2' then begin
    Next := TSubMenu1.Create;
    Self.Start(Next);
    Next.Free;
  end;
end;

Другой мой вопрос: какой будет подходящий способ обмена данными между меню? Например, если бы я хотел, чтобы мой класс TSubMenu1 возвращал строку при вызове метода, как бы я сделал его доступным в другие подменю, которые не взаимодействуют с ним? (Извините, если вопрос расплывчатый). Я имею в виду шаблон Singleton, но я также подумал о том, чтобы менеджер UI сохранял ссылку на некоторый объект для хранения данных, и каждый раз, когда запускается новое подменю, передайте ссылку на новое подменю (UI менеджер). Загадка - выяснить, какой из них работает лучше всего. Или даже если мой управляемый меню фреймворк приличный.

Мнения приветствуются, и любые советы приветствуются. Спасибо за ваше время и помощь!

- Тодд

Ответы [ 2 ]

0 голосов
/ 13 января 2011

«Мой другой вопрос: каков подходящий способ обмена данными между меню?»

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

Ниже приведен пример кода, который поделится List.

type
  TForm1 = class(TForm)
    ---
    ---
  private
    { Private declarations }
    class var List: TStringList;
    ---
  end;
var
  Form1, Form2: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.List.Add('4');
  Form2.List.Add('5');

  ShowMessage(TForm1.List.Text);
end;

initialization
  StrList := TStringList.Create;
  TForm1.List := TStringList.Create;
  TForm1.List.Add('1');
  TForm1.List.Add('2');
  TForm1.List.Add('3');
  ShowMessage(TForm1.List.Text);


finalization
  FreeAndNil(TForm1.List);
end.
0 голосов
/ 13 января 2011

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

procedure TMenu1.OnEvent (c: Char);
var
  Next: TExtendedUIManager;
begin
  if c = '2' then begin
    Next := TSubMenu1.Create;
    Self.Start(Next);
    Next.Free;
  end;
end;

Такое ощущение, что конечным условием такого рода программирования будут огромные деревья решений if c = '2' then ... else if c = '3' then ... else и так далее. Это действительно утомительно писать и поддерживать; если это возможно, входной символ отображения массива с функцией для выполнения часто гораздо проще поддерживать.

[['2', foo_create],
['3', foo_delete],
['4', foo_ship],
['d', foo_destroy_all],
['`', foo_return_to_previous_menu]]

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

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

/* key function    arg   ret types */
[['2', foo_create, NULL, FOO],
['3', foo_delete, FOO, NULL],
['4', foo_ship, FOO, NULL],
['d', foo_destroy_all, NULL, NULL],
['`', foo_return_to_previous_menu, NULL, NULL]]

Надеюсь, это полезно каким-то образом. :)

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