记一次用设计模式重构代码的经验

    最近半年在做区块链钱包App的iOS端的开发。

    区块链app开发,印象最明显的地方就是,区块链由于币种非常多,不同币种数据结构和处理方法又不完全一样,而每个币种的界面又几乎是一样的。

    所以我习惯性地在各种控制器中,用大量if else去判断币种类型,然后分开去处理不同的业务逻辑。

    如下面:

      页面A为某个币种的交易列表页,关键地方伪代码如下:

    if(币种==ETH){

    ETH接取交易列表

    }else if (币种 == ETH Token){

    ETH Token接取交易列表

    }else{

    常规拉取交易列表

    }

 

    而在其它页面如交易发送页B,交易详情确认页C中也出现了大量上面这样的if else写法。

    我们的app叫IFWallet(国外商店下载),其中几个页面如下:

 

资产页

 

交易记录页

 

发送页

    直到有一天,我想我要做出改变,用我知道的设计模式去重构代码。

    首先我想到的是,将if else中的每一种处理逻辑,用block来封装,然后由一个统一的方法输入币种返回处理的block。

    伪代码如下:

    - (block)fetchBusinessBlockForCoin:(币种){

        if(币种==ETH){  

        return ETH-Block;

        }else if (币种 == ETH Token){

        return ETH-Token-Block;

        }

        return 常规-Block;

    }

    但后面我想,这种方法只是抽出了逻辑到另一个地方而已。

    我想,以前的代码最大问题在于,各个页面都有大量的if else, 势必难以维护和拓展。如果增加一种币种,就要去四五个页面改if else代码。容易漏掉,也难阅读。

    于是,我想到了,能不能在一个地方一次性地指定不同币种由什么样的逻辑去处理?

    因此,我想到了,将一个币种的所有业务封装成一个对象CB,伪代码如下:

class 币种业务类CB {

(成员变量:)  

交易记录拉取类HF对象;

交易构建类DC对象;

交易发送类DS对象;

}

    这样,不同币种的不同业务可以去继承HF,DC,DS类,等于是用组合模式,把不同的业务的处理对象,组合成一个整体的币种处理对象。

    然后,我们再用工厂方法模式,去为不同的币种创建对应的币种业务类CB对象。伪代码如下:

class 币种业务类工厂类CB factory{

+ (币种业务类CB对象)buildCBWithCoin:(币种){

  币种业务类CB对象 cb

  if(币种==ETH){  

        cb. 交易记录拉取类HF对象 = ETH 交易记录拉取类HF对象;    

        cb.交易构建类DC对象 = ETH交易构建类DC对象;

        cb.交易发送类DS对象 = ETH交易发送类DS对象;

        }else if (币种 == ETH Token){

        cb. 交易记录拉取类HF对象 = ETH Token交易记录拉取类HF对象;

        cb.交易构建类DC对象 = ETH Token交易构建类DC对象;

        cb.交易发送类DS对象 = ETH Token交易发送类DS对象;

        }else{

    cb. 交易记录拉取类HF对象 = 常规交易记录拉取类HF对象;

        cb.交易构建类DC对象 = 常规交易构建类DC对象;

        cb.交易发送类DS对象 = 常规交易发送类DS对象;

    }

        return cb;

}

}

    也就是说,币种的某一业务,会因币种不同而不一样,不同的实现只需继承自同一个父类即可,如“ETH 交易记录拉取类HF”和 “常规交易记录拉取类HF”,“常规交易构建类DC” 都 继承自 交易记录拉取类HF;

    然后在不同的几个页面,就可以直接调用父类的方法,就会根据多态,而去决定用哪个子类的具体实现去处理这个币种的业务。

    因此,在我们拿到币种时,就配好了相应的业务处理方法,只需一次性用if else配置好,后面就再也不用写if else了,代码简洁,同时,改动或增加币种时,只城增加业务类,和修改工厂类就行了,不用去各个页面改动。维护成本,大大降低。

    我个人认为,很多时候我们写代码使用面向对象思想仅停留在了“使用对象"的层面上,而没用将"业务和逻辑"也应用面向对象思想。

    设计模式真是个好东西,请善待它。  

 

唐京

2019/04/11

/* * 原始需求背景: * 网宿CDN要按月收取客户的服务费用,根据流量的大小、 * 服务的类型等,收取不同的费用,收费规则如下: * web应用:1000元/M * 流媒体应用:1000元/M*0.7 * 下载应用:1000元/M*0.5 * 月末打印报表时,要罗列每个用户每个频道的费用、客户总费用, * 还要打印该客户的重要性指数,重要性指数=网页流/100+下载流量/600; * * 需求变更场景: * 系统已经开发出来了,接下来,运维部门现在希望对系统做一点修改, * 首先,他们希望能够输出xml,这样可以被其它系统读取和处理,但是, * 这段代码根本不可能在输出xml的代码中复用report()的任何行为,唯一 * 可以做的就是重写一个xmlReport(),大量重复report()中的行为,当然, * 现在这个修改还不费劲,拷贝一份report()直接修改就是了。 * 不久,成本中心又要求修改计费规则,于是我们必须同时修改xmlReport() * 和report(),并确保其一致性,当后续还要修改的时候,复制-黏贴的问题就 * 浮现出来了,这造成了潜在的威胁。 * 再后来,客服部门希望修改服务类型和用户重要性指数的计算规则, * 但还没决定怎么改,他们设想了几种方案,这些方案会影响用户的计费规则, * 程序必须再次同时修改xmlReport()和report(),随着各种规则变得越来越复杂, * 适当的修改点越 来越难找,不犯错误的机会越来越少。 * 现在,我们运用所学的OO原则和方法开始进行改写吧。 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值