想了好久要不要叫優化後的單例模式的,還是承受不住這個標題的誘惑,於是乎就叫優化後的單例模式吧!
事情的起源是這樣的,先來一張圖:
看着有點亂我來解釋一下:可以看到下機這個按鈕竟然跑到學生餘額查詢這個窗體的上方了,也就是說主窗體的控件全部在子窗體的上方!!!這還了得,這樣就不能用了啊!對於這個大家一定也有經驗,問題出在MDI窗體上,然後經過本人多次試驗得出結論:除非新實例化的窗體不是主窗體的子窗體,否則這是不可調和的一對矛盾!(當然你可以用類似VB中我們用過的方法一樣來解決).
如果利用我們以前一樣的方法,可以添加如下的代碼:
<span style="font-family:KaiTi_GB2312;font-size:18px;">using System.Runtime.InteropServices;
[DllImport("user32")]
public static extern int SetParent(int hWndChild, int hWndNewParent);
Form2 f2 = new Form2();
f2.MdiParent = this;
f2.Show();
SetParent((int)f2.Handle, (int)this.Handle);</span>
但是相對於要實例化誰由誰來控制的單例模式來說,這段片段不太符合面向對象的思想,於是乎就大膽的決定,放棄MDI窗體的應用,爲什麼呢?還要從MDI窗體的源頭說起.MDI窗體是微軟公司從Windows 2.0下的Microsoft Excel電子表格程序開始引入的,Excel電子表格用戶有時需要同時操作多份表格,MDI正好爲這種操作多表格提供了很大的方便,於是就產生了MDI程序.上面說的很清楚,因爲同時需要打開多個表格,產生的MDI窗體,而在我們的機房中,這種需求並不是必須的,因爲我們最多就是同時打開多窗體,並且在多窗體之間切換就可以了,並不存在同時操作多窗體的需求.所以放棄MDI窗體的應用,個人認爲未嘗不可.
接着,在不使用MDI窗體的情況下就會產生一種情況,比方說:在上機界面下打開修改密碼窗體,然後切回上機界面時,修改密碼窗體任然在,卻不能通過菜單選擇獲得焦點.這種狀況應該不少人也遇到過吧,爲什麼呢?看代碼:
<span style="font-family:KaiTi_GB2312;font-size:18px;">private static frmMOdifyPW fmp = null;
private frmCheckCash()
{
InitializeComponent();
}
public static frmModifyPW GetInstance()
{
//判斷當修改密碼窗體不在或者消失後,激活
if (fmp == null || fmp.IsDisposed)
{
fmp = new frmCheckCash();//此處已將父窗體爲MDI主窗體去掉
}
return fmp;
} </span>
觀察上述代碼,此爲設計模式中的代碼片段,理解一下就是在fmp不存在或者窗口被釋放時,新實例化一個窗體,但是在我們於兩個窗體直接切換的時候,我們沒有關閉任何一個窗體,進而觸發該事件後直接返回了!而我們需要的是,要麼沒有窗體,實例化出來;要麼窗體存在,獲得焦點(好讓我使用);故而在書上經典單例模式應用於非MDI窗體後我添加了一行代碼,在返回之前,激活該窗體:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="color:#333333;"> private static frmModifyPassword fmp = null;
private frmModifyPassword()
{
InitializeComponent();
}
public static frmModifyPassword GetInstance()
{
//判斷當修改密碼窗體不在或者消失實例化,否則激活該窗體
if(fmp==null||fmp.IsDisposed)
{
fmp = new frmModifyPassword();
}
fmp.Activate();//在返回之前激活本窗體
return fmp;
} </span></span>
這樣,就可以實現在各個窗體之間切換時,不必去下方的工程中選擇原來的窗體了,再次點擊修改密碼,該窗體又會出現在程序的最上方.開始的時候比較迷信書上的代碼,像金科玉律一樣的奉行,但是畢竟情況千變文化,適合自己的纔是最好的,我們要善於學習他人的有點,同時也要具有打破常規,突破書本的勇氣.