设计模式之策略模式(工业控制)

写这篇文章的原因是:对于工业自动化上位机的编写,策略类在硬件调用的应用是相当多的。
网上很多关于策略模式的教程,简单的实现可以自行参考;
https://blog.csdn.net/alexhu2010q/article/details/102501561
这里就不做赘述了。

简单实现步骤

switch封装(原始状态)
case的抽象类提取
case子类的建立
多态实例的调用(实现成功状态)

说好处(让你有看下去的冲动)

  1. 兼容多种运动控制卡,无论增加多少种,代码都是可维护的,一个类能保证不超过500Line。
  2. 方便后期维护,能快速寻找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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值