策略模式的具體應用
1.業務場景
隨著信息化水平逐漸提升,業務部門在數據可視化方面提報了新的需求,上位機軟件在掃描槍掃描投入料時,需要將物料的詳細發送到對應的LED屏幕上。
2.初步設計
一開始,只有一個工廠提出這個需求,直接在掃描投入料的代碼的後面,增加了調用LED的委托方法(通過委托方式實現線程級別的發送,從未不影響正常業務)。滿足需求後,向LED發送數據的業務場景越來越多,比如,切換計劃、減料、掃描工位、掃描投入料。這幾種場景下可能會導致LED發送方法的同時調用,造成多線程同時出發LED自帶的DLL方法的調用,造成發送失敗的問題,基於該問題,在實際發送方法增加lock(mLockObj)的鎖控制,從未避免出現多線程調用問題。
隨著典型業務的推廣,其他工廠也逐漸開始有這種需求,但是采購的LED屏幕廠家卻不一樣,如果僅僅為了實現需求,可以在代碼中根據工廠標誌位,進行if...else if...或switch的判斷。
3.設計提升
3.1創建發送信息類
各工廠實際業務可能會出現不一致的問題, 導致LED顯示的信息不一樣,如果把信息直接以參數的形式進行傳遞,後期需要增加顯示時,涉及的修改太多,因此,將發送方法的參數提取成一個信息類,以後再擴展直接在類中擴展屬性即可,需要使用該參數時,直接調用,涉及到的修改降低到最小。
比如:
1 public class LEDParameter2 { 3 private int mScreenID; 4 5 private string mIPAddress; 6 7 private string mMessage; 8 9 private Color mForeColor; 10 11 private int mFontSize; 12 }
3.2 定義發送方法的接口,每個工廠對應一個具體的類來實現該接口。
發送接口
1 public interface ILEDDisplay2 { 3 void DisplayMessage(LEDParameter parameter); 4 }
各工廠的實現類
1 public class ALEDDisplay : ILEDDisplay 2 { 3 public void DisplayMessage(LEDParameter parameter) 4 { 5 Console.WriteLine("Using AFactory LED Display Method"); 6 } 7 } 8 9 public class BLEDDisplay : ILEDDisplay 10 { 11 public void DisplayMessage(LEDParameter parameter) 12 { 13 Console.WriteLine("Using BFactory LED Display Method"); 14 } 15 }
3.3 根據實際情況初始化實現類
1 ILEDDisplay dislay = null; 2 switch (factoryName) 3 { 4 case "A": 5 dislay = new ALEDDisplay(); 6 break; 7 case "B": 8 dislay = new BLEDDisplay(); 9 break; 10 } 11 12 //實際調用時,直接調用接口方法即可 13 var para = new LEDParameter(); 14 dislay.DisplayMessage(para);
隨著應用工廠的增加,直接創建對應的實現類即可,主程序模塊的代碼不需要進行太多變化(LED顯示參數類可能會增加屬性,需要主程序模塊進行傳遞)。
另附:
策略模式的定義:對算法的包裝,是把使用算法的責任和算法本身分割開,委派給不同的對象負責。策略模式通常把一系列的算法包裝到一系列的策略類裏面。用一句話慨括策略模式就是——“將每個算法封裝到不同的策略類中,使得它們可以互換”。
策略模式的結構圖:
該模式涉及到三個角色:
- 環境角色(Context):持有一個Strategy類的引用
- 抽象策略角色(Strategy):這是一個抽象角色,通常由一個接口或抽象類來實現。此角色給出所有具體策略類所需實現的接口。
- 具體策略角色(ConcreteStrategy):包裝了相關算法或行為。
策略模式的具體應用