寫這篇文章的原因是:對於工業自動化上位機的編寫,策略類在硬件調用的應用是相當多的。
網上很多關於策略模式的教程,簡單的實現可以自行參考;
https://blog.csdn.net/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.csdn.net/download/bayinglong/12289035
積分5分,不多,覺得寫得可以可以添加關注。
有招聘意向也可聯繫微信18588205776