设计模式之工厂模式与反射

本文探讨了设计模式中的工厂模式,并通过一个日志记录的例子分析了其应用场景和潜在问题。作者提出了一种使用工厂(包含子类抽象方法)-> 子类的设计思想,并展示了如何利用反射技术优化工厂模式,以应对新增功能时的工作量。在实际案例中,该方法提高了代码的可维护性和灵活性,特别是在处理硬件命令操作系统的指令时。

最近在研读@TerryLee关于设计模式的文章,其中读到一篇关于工厂模式的解析与范例,熟读过后另有一番见解。

原文链接 http://terrylee.cnblogs.com/archive/2006/01/04/310716.html

原文是以日志记录为基础设计,介绍了关于不同日志记录方式下的模式设计,原文使用三层的思想设计,分别为:

抽象日志操作->不同日志操作实现 

抽象日志工厂->具体日志操作示例

表面上分析,符合工厂设计模式,但是细而划分便出现一些问题。比如如果需要增加一个日志操作方式则需要首先新建日志操作然后创建新的抽象工厂,也就是需要新建两个类,结合实际的开发分析,如果在某个功能变化程度小的情况下,增加这些类可以不用耗费太多时间。但是反而想如果不是日志操作,而是某个较复杂的功能,那么带来的工作量可想而知,故自己便换了一种方式去实现。


设计思想:工厂(包含子类抽象方法)->子类

首先看一下工厂类:HandleFactory,里面定义了GetInstance()的方法用于反射获取具体实例化的对象以及Excute具体的工厂产品类的抽象方法

namespace ERui.Service.Manage.Factory
{
    public abstract class HandleFactory : SessionFactory
    {
        /// <summary>
        /// 反射获取对应执行类
        /// </summary>
        /// <param name="type">类名</param>
        /// <returns>实例化对象</returns>
        public static HandleFactory GetInstance(string type)
        {
            return (HandleFactory)Assembly.Load("ERui.Service.Manage").CreateInstance("ERui.Service.Manage.Factory." + type);
        }

        public abstract byte[] Excute(byte[] message, ERuiSession session);
    }
}


产品类:E0。

namespace ERui.Service.Manage.Factory
{
    public class E0 : HandleFactory
    {
        public override byte[] Excute(byte[] message, ERuiSession session)
        {
            var length = message.Length - 13;
            var phones = ERuiBytes.GetBytes(message, 11, length);
            var masters = Encoding.ASCII.GetBytes(BitConverter.ToString(phones, 0, phones.Length).Replace("-", ""));
            return base.SendToClient<SET_PHONEBOOK_PKT_MODEL>(session, new SET_PHONEBOOK_PKT_MODEL()
            {
                master = masters
            });
        }
    }
}



具体实现。

public override void ExecuteCommand(MangeSession session, BinaryRequestInfo requestInfo)
        {
            var message = requestInfo.Body;
            var type = BitConverter.ToString(message, 10, 1);

            //获取设备编号
            var imei = Convert.ToUInt64(BitConverter.ToString(message, 2, 8).Replace("-", "").Substring(0, 16));
            var erSession = ERuiServer.server.Get(imei);

            //执行处理
            HandleFactory handle = HandleFactory.GetInstance(type);
            var result = handle.Excute(message, erSession);
            session.Send(result, 0, result.Length);
        }


使用场景,现在公司在做一套命令操作硬件的系统,那么每个命令就是一个具体的产品,如果采用传统的方法,我们需要将接收到的命令使用if或者switch进行判断然后递交具体的类去处理,这种处理方法第一代码量大,第二可维护性差,第三功能拔插不够灵活

优化第一步:故我们使用工厂模式定义统一的处理风格即为Excute,这样就可以定义一个基类,然后使用if或者switch实例化具体的操作,最后统一执行Excute

优点:风格一致,代码量稍小,可维护性稍好

优化第二步:如果后期加入了新的指令,那就需要新建处理类和new,这时候我们就可以使用反射技术,在工厂定义GetInstance方法,传递参数为处理指令名称,我们再根据名称找到具体的处理类,这样前期处理就不用关注需要调用哪个类,如指令为E1,我们就只需要新建为E1的产品类

namespace ERui.Service.Manage.Factory
{
    public class E1 : HandleFactory
    {
        public override byte[] Excute(byte[] message, Socket.ERuiSession session)
        {
            return base.SendToClient<GET_VOICE_PKT_MODEL>(session, new GET_VOICE_PKT_MODEL()
            {
                app_account = ERui.Service.Command.ERuiBytes.GetBytes(message, 11, 6),
                amr_quality = message[18],
                amr_duration = message[19]
            });
        }
    }
}
教程到此结束,技术交流QQ群:153373508

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值