zoukankan      html  css  js  c++  java
  • 使用抽象工厂模式来解决遗留代码中的紧耦合和难维护的问题

    楼主工作的单位是一家欧洲公司,主营奢侈品的生产和销售,我们有一个PLM(产品生命周期管理系统),用来管理产品的主数据,例如对部品及物料从设计到生产,以及BOM等主数据的管理,我们采购的平台是Enovia,当然我们在这个系统中做了很多深度定制来满足我们企业的特殊需求,但凡构建过企业级系统的人都知道,一个系统不是独立存在的,它往往需要跟其他系统保持交互来协作完成工作,我们的PLM系统也是一样,我们以SOA的架构来构建系统,每个系统关注于自己所提供的服务,系统跟系统之间采用Web Service技术进行交互,Web Service又是基于HTTP协议和XML的,大家知道HTTP协议跟XML数据交换格式是平台独立的,这样我们可以就可以通过Web Service来达到异构系统(跨平台跨语言)的交互,我们PLM系统也不例外,我们不仅仅需要把主数据通过XML的形式传送到SAP,同时PLM也会跟供应商的DAM系统保持沟通,因为我们有些部品是从供应商采购的,供应商可以通过DAM系统把部品的图片发送到PLM系统,我们今天就先来聊聊PLM跟SAP数据交互实现中的问题。

    以上说的跟设计模式貌似没啥关系,但其实不是,我希望通过完整的描述来让大家理解这个问题的来龙去脉,不然仅仅提供问题和解决方案,大家看完之后还是一头雾水。

    先来说说PLM是怎样把数据发送到SAP的,我用UML活动图来描述这个流程(第一次画活动图,心里还有点小紧张呢:))

    今天我要重构的部分就在第一步,PLM生成XML的实现。 按照公司的规定,公司欢迎有建设性的意见,但是你在生产系统实现之前必须要写一个详细的方案并在测试系统实现,最后把方案文档,实现代码及测试报告一并发给PLM经理审阅,审核通过后即可发布到正式系统。

    之前,欧洲Enovia顾问(那些顾问技术很高深,但是似乎都不重视OO设计,完全是按照面向过程的思维来写代码的)为了尽量不创建新的Java类,就把POJO,接口以及工厂方法的实现全都写在一个类里面,现在随着业务代码量的增加,我们有一个超级大的工厂方法,细数起来那个方法竟然有2278行!而且如果现在不加以改进,以后代码行数还会更多,工厂方法可以解决一些耦合的问题,但是把所有的接口,POJO及工厂方法的实现放在一个类,这个方法的缺点就显而易见了:

    1. 该工厂方法难以维护,并且违背了OO设计高内聚低耦合的原则。

    2. 如果用户有新的需求例如新增一个XML segment到PLM生成的XML文件中,很难定位到底应该改哪个地方。

    3. 更搞笑的是,我们竟然没有发现在代码里面有3处重复的代码块!

    总之,当前策略对于PLM导出功能的可维护性,可扩展性都不利,原因就是顾问采用了工厂方法模式来处理这种工厂方法无法胜任的情况。

    那么如何解决这种问题?

    我觉得使用抽象工厂模式+工厂方法模式可以有效解决这个问题,首先来看看类图:

    抽象产品类及其具体实现类:

    抽象工厂方法类及其具体实现类:

    我第一步要做的就是把之前定义在超级大类里面的接口独立出来一个单独的文件用来作为抽象产品的抽象类,然后把之前超大的工厂方法依据不同的代码块分成25个小类; 第二部就是定义一个抽象工厂接口,接口里面有一个create方法负责依据methodName创建那25个对象,该接口有一个具体实现类,该实现类的create方法依然采用工厂方法模式。可惜目前Enovia内核JDK还是1.6的,我无法使用switch(String),只能使用难看的if...else...来解决了。

    我把重构方案文档,具体实现代码及测试报告发送给欧洲PLM项目经理审阅,本身我是没有抱审核通过的期望的,因为我之前对于项目的改进提过一些关于解耦和性能的建议,但是PLM经理是一个比较守旧的人(说白了就是害怕改变),每次都不了了之,所以已经打击我积极性很多次了,但是这次不知道为什么,不到半小时他就回复我:

    I like your proposal implement it thanks

    我当时心情真是太激动了。

    下一步要做的就是把那些硬编码在代码里面的静态Map抽取出来放到资源文件里面,这样tomcat已启动的时候就可以把资源加载到内存,提高了读取的效率。

  • 相关阅读:
    centos8 将SSSD配置为使用LDAP并要求TLS身份验证
    Centos8 搭建 kafka2.8 .net5 简单使用kafka
    .net core 3.1 ActionFilter 拦截器 偶然 OnActionExecuting 中HttpContext.Session.Id 为空字符串 的问题
    Springboot根据不同环境加载对应的配置
    VMware Workstation12 安装 Centos8.3
    .net core json配置文件小结
    springboot mybatisplus createtime和updatetime自动填充
    .net core autofac依赖注入简洁版
    .Net Core 使用 redis 存储 session
    .Net Core 接入 RocketMQ
  • 原文地址:https://www.cnblogs.com/stonefeng/p/5720705.html
Copyright © 2011-2022 走看看