策略模式強調不同方法(如抓影像特徵的演算法), 將他們個別封裝起來且彼此可以互相切換(因為繼承相同抽象類別),
客戶端呼叫取影像特徵方法的名稱都一樣叫做getFeatures(),
根據方法1: 實體化不同的策略的衍生類別決定使用哪種演算法 或是方法2: 傳入字串自動切換底層不同的演算法
以下會進一步說明
新增一個windows form專案
選擇該StrtegyPatternGetImageFeatures專案, 滑鼠右鍵 <加入><新增項目>
定義interface: iFeature
裡面包含定義GetFeatures()方法, 至於如何實作則留給繼承的iSIFT和iSURF
1: public interface iFeature
2: {
3: // method 清單
4: void GetFeatures();
5: }
1: // interface : 先實作取得影像特徵的方法
2: public class iSIFT : iFeature
3: {
4: public void GetFeatures()
5: {
6: MessageBox.Show("在此實作SIFT...");
7: }
8: }
9: public class iSURF : iFeature
10: {
11: public void GetFeatures()
12: {
13: MessageBox.Show("在此實作SURF...");
14: }
15: }
1: // 定義一個抽象類別
2: public abstract class FeatureStrategy
3: {
4: public iFeature m_IFeature; //interface 資料成員
5: // 預設建構子
6: public FeatureStrategy() { }
7: // 有參數的建構子: 傳入指定方法
8: public FeatureStrategy(iFeature fs)
9: {
10: m_IFeature = fs;
11: }
12: // 成員方法: 指定特定方法
13: public void setIFeature(iFeature fs)
14: {
15: m_IFeature = fs;
16: }
17: //-----------------------------------------
18: // 成員方法: 執行GetFeatures
19: public void getFeatures()
20: {
21: m_IFeature.GetFeatures();
22: }
23: }
1: //(1) SIFT策略繼承特徵策略抽像類別
2: public class SIFTStrategy : FeatureStrategy
3: {
4: // 預設建構子: 順便初始化m_IFeature
5: public SIFTStrategy()
6: {
7: m_IFeature = new iSIFT();
8: }
9: }
1: // (2) SURF策略繼承特徵策略抽像類別
2: public class SURFStrategy : FeatureStrategy
3: {
4: // 預設建構子: 順便初始化m_IFeature
5: public SURFStrategy()
6: {
7: m_IFeature = new iSURF();
8: }
9: // 有參數的建構子: 傳入指定方法字串, 透過字串決定m_IFeature選擇哪種策略方法
10: public SURFStrategy(string method)
11: {
12: if (method == "SIFT")
13: {
14: m_IFeature = new iSIFT();
15: }
16: else
17: {
18: m_IFeature = new iSURF();
19: }
20:
21: }
22: }
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
測試Strategy Pattern
方法1: 實體化不同的策略的衍生類別決定使用哪種演算法
可以發現宣告選擇FeatureStrategy抽象類別, 實體化fs,則以繼承該抽象類別的子類別 SIFTStrategy
1: private void button1_Click(object sender, EventArgs e)
2: {
3: FeatureStrategy fs = new SIFTStrategy();
4: fs.getFeatures();
5: }
按下SIFT按鈕跳出
可以發現宣告選擇FeatureStrategy抽象類別, 實體化FS則以繼承該抽象類別的子類別 SURFStrategy
1: private void button2_Click(object sender, EventArgs e)
2: {
3: FeatureStrategy FS = new SURFStrategy();
4: FS.getFeatures();
5: }
方法2: 傳入字串自動切換底層不同的演算法
根據下拉選單選擇的方法不同(字串), 決定使用不同策略
對客戶端而言都是呼叫 fs.getFeatures() 方便管理
1: private void button3_Click(object sender, EventArgs e)
2: {
3: FeatureStrategy fs = new SURFStrategy(comboBox1.Text);
4: fs.getFeatures();
5: }
宣告SIFTStrategy類別, 可以利用setIFeature() 傳入另一種方法iSURF()
讓客戶端直接切換另一種方法, 而不用再另外實體化一個new SURFStrategy()
PS. 因為SIFTStrategy和SURFStrategy都繼承抽象類別FeatureStrategy
1: private void button4_Click(object sender, EventArgs e)
2: {
3: FeatureStrategy fs = new SIFTStrategy();
4: fs.getFeatures();
5: fs.setIFeature( new iSURF() ); // 改指定別的方法iSURF
6: fs.getFeatures();
7: }
如果臨時又想增加新的抓影像特徵方法
1: // 臨時又想增加新的抓影像特徵方法
2: public class iHOG : iFeature
3: {
4: public void GetFeatures()
5: {
6: MessageBox.Show("在此實作HOG...");
7: }
8: }
1: private void button5_Click(object sender, EventArgs e)
2: {
3: FeatureStrategy fs = new SIFTStrategy();
4: fs.setIFeature(new iHOG());
5: fs.getFeatures();
6: }
延伸閱讀: