1.业务场景
随着信息化水平逐渐提升,业务部门在数据可视化方面提报了新的需求,上位机软件在扫描枪扫描投入料时,需要将物料的详细发送到对应的LED屏幕上。
2.初步设计
一开始,只有一个工厂提出这个需求,直接在扫描投入料的代码的后面,增加了调用LED的委托方法(通过委托方式实现线程级别的发送,从未不影响正常业务)。满足需求后,向LED发送数据的业务场景越来越多,比如,切换计划、减料、扫描工位、扫描投入料。这几种场景下可能会导致LED发送方法的同时调用,造成多线程同时出发LED自带的DLL方法的调用,造成发送失败的问题,基于该问题,在实际发送方法增加lock(mLockObj)的锁控制,从未避免出现多线程调用问题。
随着典型业务的推广,其他工厂也逐渐开始有这种需求,但是采购的LED屏幕厂家却不一样,如果仅仅为了实现需求,可以在代码中根据工厂标志位,进行if...else if...或switch的判断。
3.设计提升
3.1创建发送信息类
各工厂实际业务可能会出现不一致的问题, 导致LED显示的信息不一样,如果把信息直接以参数的形式进行传递,后期需要增加显示时,涉及的修改太多,因此,将发送方法的参数提取成一个信息类,以后再扩展直接在类中扩展属性即可,需要使用该参数时,直接调用,涉及到的修改降低到最小。
比如:
1 public class LEDParameter 2 { 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 ILEDDisplay 2 { 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):包装了相关算法或行为。