前段時間學習了一些設計模式,最近在做項目的過程中恰巧用到了其中的一個--模板方法模式。這個模式在程序設計過程中可是爲小編省去了不少的代碼量呢。具體是怎樣應用的呢?接下來小編爲您分享。 |
※功能需求
在程序設計過程中,有兩個以上的窗口是實現組合查詢功能,且基本結構都包括字段名、操作符、要查詢的內容,以及操作符之間的組合關係,查出結果後將其導出、且導出的文件類型爲Excel表。
在實現上面的功能時,考慮到這些窗口有類似的實現流程,所以就採用了一個設計模式----模板方法模式來實現功能需求。
1、首先建立一個模板,即父窗體。
把不同窗體中具有的相同結構都放在父窗體中,且在父窗體的代碼中編寫它們公有的事件和方法,以及實現特定功能的模板方法----虛方法,涉及到的具體的實現功能的查詢方法需要在具體實現功能的窗體中去寫[類似於接口一樣,只提供抽象的方法,具體實現方法在D層中來實現。這裏採用虛方法,在子窗體中進行重寫]。在這個模板裏,小編寫的方法和事件有以下這些:
namespace UI
{
public partial class frmGroupFindFather : Form
{
public frmGroupFindFather()
{
InitializeComponent();
}
//查詢
private void btnQuerry_Click(object sender, EventArgs e)
{
//判斷在容器panel上的控件 屬性值 enabled爲true的控件裏的內容不能爲空
foreach (Control c1 in panel2.Controls)
{
if ((c1 is ComboBox||c1 is TextBox)&&c1 .Enabled ==true)
{
if (c1 .Text.Trim()=="")
{
MessageBox.Show("請將信息填寫完整!", "提示");
return;
}
}
}
GroupFindtemplateFacade FGroupFind = new GroupFindtemplateFacade();//實例化外觀層
GroupFindtemplate groupInfo = new GroupFindtemplate();//實例化實體層
//爲實體層賦值
groupInfo.Dbtable = GetDbTableName();
groupInfo.CboFiled1 =GetEndlishFromFiled( CboFiled1.Text.Trim()); //字段需要採用中英轉換的方法
groupInfo.CboFiled2 =GetEndlishFromFiled( CboFiled2.Text.Trim());
groupInfo.CboField3 = CboFiled3.Text.Trim();
groupInfo.CboMark1 = CboMark1.Text.Trim();
groupInfo.CboMark2 = CboMark2.Text.Trim();
groupInfo.CboMark3 = CboMark3.Text.Trim();
groupInfo.Cbotent1 = txtCbotent1.Text.Trim();
groupInfo.Cbotent2 = txtCbotent2.Text.Trim();
groupInfo.Cbotent3 = txtCbotent3.Text.Trim();
groupInfo.Relationship1 = GetEndlishFromFiled(cboConbination1.Text.Trim());
groupInfo.Relationship2 = GetEndlishFromFiled(cboConbination2.Text.Trim());
bool flag = false;
flag = FGroupFind.GroupFindtemplate(groupInfo);
if (flag==true)
{
MessageBox.Show("查找成功!");
DataTable dt = new DataTable();
dt = FGroupFind.GroupFindTable(groupInfo);
dgv.DataSource = dt;
dgv.AllowUserToAddRows = false;
}
else
{
MessageBox.Show("無法查詢您輸入的信息,請重新輸入!");
}
}
//清空
private void btnClear_Click(object sender, EventArgs e)
{
Clear();//調用封裝好的清空方法
DataTable Table = null;
dgv.DataSource = Table;
LoadControl();//控件初始化方法
}
//清空的方法
private void Clear()
{
foreach (Control c1 in panel2.Controls)
{
if (c1 is ComboBox||c1 is TextBox )
{
c1.Text = "";
}
}
cboConbination1.Text = "";
cboConbination2.Text = "";
}
//控件初始化方法
private void LoadControl()
{
CboFiled2.Enabled = false;
CboFiled3.Enabled = false;
CboMark2.Enabled = false;
CboMark3.Enabled = false;
txtCbotent2.Enabled = false;
txtCbotent3.Enabled = false;
cboConbination1.Enabled = false;
cboConbination2.Enabled = false;
}
//窗體加載的方法
private void frmGroupFindFather_Load(object sender, EventArgs e)
{
LoadControl();//調用控件初始化方法
}
//當第一行的文本填充完整後,第一個組合關係被激活
private void txtCbotent1_TextChanged_1(object sender, EventArgs e)
{
if (CboFiled1.Text != "" && CboMark1.Text != "" && txtCbotent1.Text != "")
{
cboConbination1.Enabled = true;
}
}
//當選擇第一個組合關係時 出現第二行信息框
private void cboConbination1_SelectedIndexChanged_1(object sender, EventArgs e)
{
if (cboConbination1.Text != "")
{
CboFiled2.Enabled = true;
CboMark2.Enabled = true;
txtCbotent2.Enabled = true;
}
}
//當第二行的文本填充完整後,第二個組合關係被激活
private void txtCbotent2_TextChanged(object sender, EventArgs e)
{
if (CboFiled2.Text != "" && CboMark2.Text != "" && txtCbotent2.Text != "")
{
cboConbination2.Enabled = true;
}
}
//當選擇第二個組合關係時 出現第三行信息框
private void cboConbination2_SelectedIndexChanged_1(object sender, EventArgs e)
{
if (cboConbination2.Text != "")
{
CboFiled3.Enabled = true;
CboMark3.Enabled = true;
txtCbotent3.Enabled = true;
}
}
//構造一個沒有任何返回值的虛方法 來根據字段內容出現相應的下拉內容
public virtual void addcontent(ComboBox file,ComboBox mark)
{
}
#region 以下三個方法是根據字段的內容添加符號內容
public void CboFiled1_SelectedIndexChanged(object sender, EventArgs e)
{
addcontent(CboFiled1, CboMark1);
}
public void CboFiled2_SelectedIndexChanged(object sender, EventArgs e)
{
addcontent(CboFiled2, CboMark2);
}
public void CboFiled3_SelectedIndexChanged(object sender, EventArgs e)
{
addcontent(CboFiled3, CboMark3);
}
#endregion
//定義一個數據庫中不同表的名字的虛方法 在子窗體中進行重寫,需要查詢哪個表 就返回該表的表名
public virtual string GetDbTableName()
{
return "";
}
//轉換中文字符爲英文字符,在字窗體就進行重寫
public virtual string GetEndlishFromFiled(string cbo)
{
return "";
}
注:父窗體的其他層編碼方式與一般窗體編碼形式類似,區別較大的就是DAL層。在這裏,小編使用了存儲過程。
2、然後創建具體實現特定功能窗口,即子窗體。
在子窗體中對父窗體裏的虛方法進行重寫,滿足不同子窗體實現不同的、具體的功能。下面以Line_Info表爲例:
//方法重寫:根據字段 添加操作符
public override void addcontent(ComboBox cbofiled, ComboBox cbomark)
{
switch (cbofiled.Text)
{
case "用戶名":
case "性別":
case "狀態":
cbomark.Text = "";
cbomark.Items.Clear();
cbomark.Items.Add("=");
cbomark.Items.Add("<>");
break;
case "卡號":
cbomark.Text = "";
cbomark.Items.Clear();
cbomark.Items.Add("=");
cbomark.Items.Add("<>");
cbomark.Items.Add(">");
cbomark.Items.Add("<");
break;
}
}
//方法重寫:獲取數據庫中表的名字的方法
public override string GetDbTableName()
{
return "Line_Info";
}
//方法重寫:將中文轉換成數據庫中相應字段的方法
public override string GetEndlishFromFiled(string cbo)
{
switch (cbo)
{
case "用戶名":
return "UserID";
case "性別":
return "sex";
case "狀態":
return "status";
case "卡號":
return "cardno";
case "或":
return "OR";
case "且":
return "AND";
default:
return "";
}
}
注:其餘的事件和方法在父窗體中已有定義,在子窗體中無需再寫了。
看了上面的分享,是不是感覺模板方法模式能爲我們程序設計節省不少代碼呢。在程序設計過程中,恰當的運用設計模式能達到事半功倍的效果呢。 |