写这篇文章的原因是:对于工业自动化上位机的编写,策略类在硬件调用的应用是相当多的。
网上很多关于策略模式的教程,简单的实现可以自行参考;
https://blog.youkuaiyun.com/alexhu2010q/article/details/102501561
这里就不做赘述了。
简单实现步骤
switch封装(原始状态)
case的抽象类提取
case子类的建立
多态实例的调用(实现成功状态)
说好处(让你有看下去的冲动)
- 兼容多种运动控制卡,无论增加多少种,代码都是可维护的,一个类能保证不超过500Line。
- 方便后期维护,能快速寻找Bug,修改过程不用担心破坏代码结构。
为什么会有上述好处
说白了就是符合SOLID设计基本原则,单一功能、开闭原则、里氏替换、接口隔离以及依赖反转。不是王婆卖瓜自卖自夸,是确实很多公司是使用Switch case的原始写法。
原始写法
/*****************************************************
** 命名空间: ConsoleApp2
** 文 件 名:AxisCard
** 内容简述:
** 版 本:V1.0
** 创 建 人:Byron
** 创建日期:2020/3/31 18:28:32
** 修改记录:
日期 版本 修改人 修改内容
*****************************************************/
namespace ConsoleApp2
{
public class AxisCard
{
public CardTypeEnum cardType = CardTypeEnum.NULL;
public bool initSuccess = false;
public void Print(string cmd)
{
System.Diagnostics.Debug.WriteLine(cmd);
}
public void InitCard(CardTypeEnum cardType)
{
this.cardType = cardType;
switch (cardType)
{
case CardTypeEnum.研华:
Print("研华控制卡初始化成功");
initSuccess = true;
break;
case CardTypeEnum.雷赛:
Print("雷赛控制卡初始化成功");
initSuccess = true;
break;
case CardTypeEnum.众为兴:
Print("众为兴控制卡初始化成功");
initSuccess = true;
break;
}
}
/// <summary>
/// 移动轴
/// </summary>
/// <param name="axisNum"></param>
/// <param name="pos"></param>
public void AxisMoveAbs(int axisNum, double pos)
{
switch (cardType)
{
case CardTypeEnum.研华:
Print("研华控制卡移动" + pos);
initSuccess = true;
break;
case CardTypeEnum.雷赛:
Print("雷赛控制卡移动" + pos);
initSuccess = true;
break;
case CardTypeEnum.众为兴:
Print("众为兴控制卡移动" + pos);
initSuccess = true;
break;
}
}
/// <summary>
/// 获取单个输出
/// </summary>
/// <param name="IOindex"></param>
/// <returns></returns>
public bool GetInput(int IOindex)
{
switch (cardType)
{
case CardTypeEnum.研华:
return true;
case CardTypeEnum.雷赛:
return true;
case CardTypeEnum.众为兴:
return true;
}
return false;
}
}
public enum CardTypeEnum
{
NULL,
台达,
研华,
雷赛,
众为兴,
ByronCard,
//************************
}
}
写了一小段,个人比较懒,不想列出太多,这种写法增加了我的惰性;、
改进后写法
case的抽象类提取
/*****************************************************
** 命名空间: ConsoleApp2
** 文 件 名:ICard
** 内容简述:
** 版 本:V1.0
** 创 建 人:Byron
** 创建日期:2020/3/31 18:47:47
** 修改记录:
日期 版本 修改人 修改内容
*****************************************************/
namespace ConsoleApp2.Card
{
/// <summary>
/// 卡接口
/// </summary>
internal interface ICard
{
void InitCard();
void AxisMoveAbs(int axisNum, double pos);
bool GetInput(int Ioindex);
}
}
case子类的建立
/*****************************************************
** 命名空间: ConsoleApp2
** 文 件 名:雷赛Card
** 内容简述:
** 版 本:V1.0
** 创 建 人:Byron
** 创建日期:2020/3/31 18:50:49
** 修改记录:
日期 版本 修改人 修改内容
*****************************************************/
namespace ConsoleApp2.Card
{
internal class 雷赛Card : ICard
{
public void Print(string cmd)
{
System.Diagnostics.Debug.WriteLine(cmd);
}
public void AxisMoveAbs(int axisNum, double pos)
{
Print("雷赛卡轴移动" + pos);
}
public bool GetInput(int Ioindex)
{
Print("获取雷赛卡IO");
return true;
}
public void InitCard()
{
Print("雷赛卡初始化");
}
}
}
/*****************************************************
** 命名空间: ConsoleApp2
** 文 件 名:雷赛Card
** 内容简述:
** 版 本:V1.0
** 创 建 人:Byron
** 创建日期:2020/3/31 18:50:49
** 修改记录:
日期 版本 修改人 修改内容
*****************************************************/
namespace ConsoleApp2.Card
{
internal class 研华Card : ICard
{
public void Print(string cmd)
{
System.Diagnostics.Debug.WriteLine(cmd);
}
public void AxisMoveAbs(int axisNum, double pos)
{
Print("研华卡轴移动" + pos);
}
public bool GetInput(int Ioindex)
{
Print("获取研华卡IO");
return true;
}
public void InitCard()
{
Print("研华卡初始化");
}
}
}
/*****************************************************
** 命名空间: ConsoleApp2
** 文 件 名:雷赛Card
** 内容简述:
** 版 本:V1.0
** 创 建 人:Byron
** 创建日期:2020/3/31 18:50:49
** 修改记录:
日期 版本 修改人 修改内容
*****************************************************/
namespace ConsoleApp2.Card
{
internal class 众为兴Card : ICard
{
public void Print(string cmd)
{
System.Diagnostics.Debug.WriteLine(cmd);
}
public void AxisMoveAbs(int axisNum, double pos)
{
Print("众为兴卡轴移动" + pos);
}
public bool GetInput(int Ioindex)
{
Print("获取众为兴卡IO");
return true;
}
public void InitCard()
{
Print("众为兴卡初始化");
}
}
}
多态实例的调用(实现成功状态)
这里实现不自觉的用上了简单工厂模式,不是有意的,后面有机会会出一篇简单工厂在工业控制的应用。
/*****************************************************
** 命名空间: ConsoleApp2.Card
** 文 件 名:CardContext
** 内容简述:
** 版 本:V1.0
** 创 建 人:Byron
** 创建日期:2020/3/31 18:57:50
** 修改记录:
日期 版本 修改人 修改内容
*****************************************************/
using System.Collections.Generic;
namespace ConsoleApp2.Card
{
internal class CardContext
{
private static Dictionary<CardTypeEnum, ICard> CardDictionary = new Dictionary<CardTypeEnum, ICard>();
public void AxisMoveAbs(CardTypeEnum Card, int axisNum, double pos)
{
CardDictionary[Card].AxisMoveAbs(axisNum, pos);
}
public bool GetInput(CardTypeEnum Card, int Ioindex)
{
return CardDictionary[Card].GetInput(Ioindex);
}
public void InitCard(CardTypeEnum Card)
{
CardDictionary[Card].InitCard();
}
//初始化容器
public void InitContext(List<CardTypeEnum> CardList)
{
foreach (CardTypeEnum item in CardList)//注册
{
switch (item)
{
case CardTypeEnum.NULL:
break;
case CardTypeEnum.台达:
break;
case CardTypeEnum.研华:
CardDictionary.Add(CardTypeEnum.研华, new 研华Card());
break;
case CardTypeEnum.雷赛:
CardDictionary.Add(CardTypeEnum.雷赛, new 雷赛Card());
break;
case CardTypeEnum.众为兴:
CardDictionary.Add(CardTypeEnum.众为兴, new 众为兴Card());
break;
case CardTypeEnum.ByronCard:
break;
default:
break;
}
}
}
}
}
实验
using ConsoleApp2.Card;
using System.Collections.Generic;
namespace ConsoleApp2
{
internal class Program
{
private static void Main(string[] args)
{
原始模式实验
AxisCard axisCard = new AxisCard();
axisCard.InitCard(CardTypeEnum.研华);
axisCard.AxisMoveAbs(1, 1000);
axisCard.GetInput(7);
CardContext cardContext = new CardContext();
cardContext.InitContext(new List<CardTypeEnum>() { CardTypeEnum.研华 });
cardContext.InitCard(CardTypeEnum.研华);
cardContext.AxisMoveAbs(CardTypeEnum.研华, 1, 1000);
cardContext.GetInput(CardTypeEnum.研华, 7);
}
}
}
结果
总结
写到这里,好处应该是已经可以看到非常明白了,原始模式的AxisCard的这个类会随着兼容卡的增加越来越多,只要有一粒老鼠,这个类在后期兼容十几种卡的时候随时都有可能爆炸。
上面的例子是卡,同样大多数的控制硬件都可以用这种方式实现,达到解耦的目的,例如镭射测高,欧姆龙,基恩士,松下,国产,用一个策略模式都可以轻松实现解耦。
实验的源代码我会上传,链接https://download.youkuaiyun.com/download/bayinglong/12289035
积分5分,不多,觉得写得可以可以添加关注。
有招聘意向也可联系微信18588205776