Должен ли мой диалог ожидания реализовать шаблон Singleton? - PullRequest
2 голосов
/ 14 ноября 2010

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

public partial class WaitDialog : Form
{
    WaitDialog()
    {
        InitializeComponent();
    }

    public static WaitDialog Instance
    {
        get { return WaitDialogCreator.uniqueInstance; }
    }

    public DialogResult ShowDialog(Form owner, string message)
    {
        Instance.lblWaitMessage.Text = message;

        return Instance.ShowDialog(owner);
    }

    public DialogResult ShowDialog(Form owner, BackgroundWorker worker)
    {
        ...
    }

    public DialogResult ShowDialog(Form owner, string message, BackgroundWorker worker)
    {
        ...
    }

    private class WaitDialogCreator
    {
        static WaitDialogCreator() { }

        internal static readonly WaitDialog uniqueInstance = new WaitDialog();
    }
}

В моем методе ShowDialog () я могу передать параметр рабочего объекта, чтобы я мог установить некоторые свойства / обработчики, которые зависят от его свойств, такие как тип используемого индикатора выполнения (marquee, если он сообщает об изменениях прогресса, непрерывный в противном случае ), возможность отменить задачу (в соответствии с реквизитом WorkerSupportsCancellation) и т. д. Метод выглядит следующим образом:

    public DialogResult ShowDialog(Form owner, BackgroundWorker worker)
    {
        if (worker == null)
        {
            throw new ArgumentNullException("worker", "A non-null worker must be provided.");
        }
        else
        {
            Instance.btnCancel.Enabled = worker.WorkerSupportsCancellation;

            //This handler close the dialog
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(onWorkerWorkComplete);

            if (worker.WorkerReportsProgress)
            {
                Instance.pbProgress.Style = ProgressBarStyle.Continuous;

                //Update the progress bar
                worker.ProgressChanged += new ProgressChangedEventHandler(onWorkerProgressChanged);
            }

            if (worker.WorkerSupportsCancellation)
            {
                Instance.btnCancel.Click += (sender, e) => { worker.CancelAsync(); };
            }
        }

        return Instance.ShowDialog(owner);
    }

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

    public Controller(Form window)
    {
        this.window = window;
        this.waitDialog = WaitDialog.Instance;
    }

    ...

    public void ShowWaitDialog(BackgroundWorker worker)
    {
        if (worker == null)
        {
            this.ShowWaitDialog();
        }
        else
        {
            window.BeginInvoke((MethodInvoker)delegate() { waitDialog.ShowDialog(window, worker); });
        }
    }

Может быть, это очень нудистский вопрос, но вот он: правильно ли применять (как я) шаблон Singleton в этом случае, или я бы выбрал нормальное создание экземпляра, учитывая, что конец класса WaitDialog обычно обрабатывает больше чем BackGroundWorker в его жизненном цикле?

Меня удивляет то, что я могу (и я буду) изменять свойства отдельного экземпляра WaitDialog каждый раз, когда я передаю новый BackGroundWorker при вызове ShowDialog (Form, BackGroundWorker). Это правильное поведение, в соответствии с шаблоном? Есть ли другой путь, который я могу выбрать для лучшей реализации? Я открыт для любых предложений.

Ответы [ 2 ]

3 голосов
/ 14 ноября 2010

Я бы каждый раз создавал новый экземпляр.

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

2 голосов
/ 14 ноября 2010

Нет, это плохая идея. Класс Form был очень разработан как одноразовый класс. Как только объект формы удален, он мертв и не может быть восстановлен. Вы получите ObjectDisposedException при попытке его отобразить снова. Чтобы предотвратить это, вам нужно перехватить событие FormClosing и остановить обработку по умолчанию. Вы можете вызвать Hide () и установить e.Cancel = true. Но теперь у вас есть проблемы с его убийством, когда вы действительно хотите избавиться от него.

Но, возможно, более убедительно, вы должны когда-либо кэшировать только те объекты, которые очень дороги для создания, но не занимают много ресурсов. Класс Form - это полная противоположность. Его создание дешево, но требует очень большого количества как управляемых, так и неуправляемых ресурсов. Особенно последнее, окно является очень дорогим объектом ОС. Это может выглядеть как создание формы дорого, но вы видите циклы, которые сжигаются на рисовании формы. Вы будете записывать одинаковое количество циклов, когда будете показывать скрытую форму.

...