“刘皓你这个混蛋被我逮住我一定搜你的魂让你生不如死。”冥王心中低吼道,同时他也想看看刘皓有什么变态功法。

“哈!”这个人突然睁开了一双紧闭的眼睛,漆黑如墨深邃无比的眼瞳闪过了一丝耀眼无比的精光,一声狂啸声从其嘴巴之中震荡而出,右手横空一削,空气之中出现了肉眼可见的波动。

金贝棋牌最新版本下载

而当脱离战斗后,蓝银皇右腿骨的能量就会先在他体内凝聚成经脉的形态,将每一根断裂的经脉彼此连接在一起,形成正常经脉的沟通,令血液重新循环起来,然后再通过这份力量,将牵引着的断裂经脉渐渐愈合。这也是为什么唐三的魂力能够恢复那么快的重要原因了。
不过很快他注意到我爱罗和手鞠用看白痴的目光看着他,顿时让他反应过来了,很明心这是为了掩饰他和砂隐忍者村的关系才这么说的,刘皓真正的目的是给我爱罗报仇。

“别把话说得太满了,一起留下他。“雷影相信在场的人都会放过这个机会,果然土影,火影,风影,水影还有他们的手下都是站起身来了,虎视眈眈的盯着刘皓,好像刘皓是他的盘中餐一样。

通过代码实例说明如何化腐朽为优雅


一、背景

​  最近我负责的活动促销系统中要在审批的时候增加计算参加活动的商品的毛利率的需求。但是我负责打辅助,主要是同事负责具体开发,我了解了他的实现方式思路以后,果断拒绝了,并给出了我的解决方案以及优点,他发现我的方案确实扩展性和可维护性更好以后就采用了,本文就来通过这个实例来说明如何让本腐朽的代码变得优雅起来。

二、需求描述

​   活动系统中共有7中活动类型,分别为:价格折扣活动、满减活动、满赠活动、换购活动、满折活动、抢购活动、N元任选活动。每种活动类型都有自己的毛利率的计算方式。要求根据不同的活动类型来通过不同的计算方式计算参加活动的商品的毛利率。

三、开发运行环境

  1. Maven 3.3.9
  2. Spring 4.2.6.RELEASE
  3. JDK 1.7
  4. IDEA 15.04

四、同事方案1

  直接通过switch/case的方式判断不同的活动类型,然后每种类型给出不同的计算方式。

package com.hafiz.www.domain;

/**
 * @author hafiz.zhang
 * @description: 活动毛利率计算器
 * @date Created in 2017/11/28 20:52.
 */
public class Calculator {

    public static String calculate(Integer campaignType) {
        switch (campaignType) {
            case 1:
                return "价格折扣活动计算毛利率";
            case 2:
                return "满减活动计算毛利率";
            case 3:
                return "满赠活动计算毛利率";
            case 4:
                return "换购活动计算毛利率";
            case 5:
                return "满折活动计算毛利率";
            case 6:
                return "抢购活动计算毛利率";
            case 7:
                return "N元任选活动计算毛利率";
            default:
                return "错误的活动类型";
        }
    }
}

 

缺点:虽然写起来很简单,但是可扩展性差,或者说不具备可扩展性,若每种活动类型的计算毛利率方式都比较复杂,则Calculator类就会变得臃肿不堪。可维护性很差。完全就是面向过程的开发方式。被我一票拒绝。并告诉他通过定义接口,然后各种活动类型实现自己的计算方式,然后使用简单工厂模式通过Java的多态来实现。

五、同事方案2

定义计算接口,被针对每种活动给出不同的实现。

1.定义计算接口

package com.hafiz.www.handler;

import com.hafiz.www.enums.CampaignTypeEnum;

/**
 * @author hafiz.zhang
 * @description: 计算毛利率接口
 * @date Created in 2017/11/28 20:57.
 */
public interface ICampaignHandler {
    /**
     * 计算毛利率
     * @return
     */
    String calculate();
}

2.价格折扣活动实现

package com.hafiz.www.handler.impl;

import com.hafiz.www.enums.CampaignTypeEnum;
import com.hafiz.www.event.CampaignHandlerEvent;
import com.hafiz.www.handler.ICampaignHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description: 价格折扣活动操作器
 * @author hafiz.zhang
 * @create 2017/11/28 20:52.
 */
public class PriceDiscountCampaignHandler implements ICampaignHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(PriceDiscountCampaignHandler.class);

    @Override
    public String calculate() {
        LOGGER.info("价格折扣活动计算毛利率");
        return "价格折扣活动计算毛利率";
    }
}

3.抢购类型活动实现

package com.hafiz.www.handler.impl;

import com.hafiz.www.enums.CampaignTypeEnum;
import com.hafiz.www.event.CampaignHandlerEvent;
import com.hafiz.www.handler.ICampaignHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description: 抢购活动操作器
 * @author: hafiz.zhang
 * @create: 2017/11/28 20:52.
 */
public class PanicBuyCampaignHandler implements ICampaignHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(PanicBuyCampaignHandler.class);

    @Override
    public String calculate() {
        LOGGER.info("抢购活动计算毛利率");
        return "抢购活动计算毛利率";
    }
}

 

等等还有剩下各种活动自己的实现,此处为避免篇幅过长略去。

4.简单工厂

package com.hafiz.www.handler;

import com.hafiz.www.handler.impl.CheapenOtherCampaignHandler;
import com.hafiz.www.handler.impl.FullCutCampaignHandler;
import com.hafiz.www.handler.impl.FullDiscountCampaignHandler;
import com.hafiz.www.handler.impl.FullGIftCampaignHandler;
import com.hafiz.www.handler.impl.OptionCampaignHandler;
import com.hafiz.www.handler.impl.PanicBuyCampaignHandler;
import com.hafiz.www.handler.impl.PriceDiscountCampaignHandler;

/**
 * @author hafiz.zhang
 * @description: 操作器工厂类
 * @date Created in 2017/11/28 22:06.
 */
public class CampaignHandlerFactory {
    public static ICampaignHandler getHandler(Integer campaignType) {
        switch (campaignType) {
            case 1:
                return new PriceDiscountCampaignHandler();
            case 2:
                return new FullCutCampaignHandler();
            case 3:
                return new FullGIftCampaignHandler();
            case 4:
                return new CheapenOtherCampaignHandler();
            case 5:
                return new FullDiscountCampaignHandler();
            case 6:
                return new PanicBuyCampaignHandler();
            case 7:
                return new OptionCampaignHandler();
            default:
                throw new RuntimeException("错误的活动类型");
        }
    }
}

 

这样比第一版稍好一点,代码已经优雅了很多,可扩展性也好了很多,如果一旦增加新的活动类型,只需要新写一个新活动计算毛利率的操作器实现类就好了,然后再在工厂类中增加对应的case.但是还是没有很完美,这样需要每次都修改工厂类,不完美!

六、我的方案:使用Spring事件通知来实现简单工厂

1.接口定义

package com.hafiz.www.handler;

import com.hafiz.www.enums.CampaignTypeEnum;

/**
 * @author hafiz.zhang
 * @description: 计算毛利率接口
 * @date Created in 2017/11/28 20:57.
 */
public interface ICampaignHandler {

    CampaignTypeEnum getCampaignType();
    /**
     * 计算毛利率
     * @return
     */
    String calculate();
}

2.活动操作器自定义事件

package com.hafiz.www.event;

import com.hafiz.www.handler.ICampaignHandler;
import org.springframework.context.ApplicationEvent;

/**
 * @author hafiz.zhang
 * @description: 活动操作器事件
 * @date Created in 2017/11/28 21:02.
 */
public class CampaignHandlerEvent extends ApplicationEvent {

    public CampaignHandlerEvent(ICampaignHandler source) {
        super(source);
    }
}

2.价格折扣现类

package com.hafiz.www.handler.impl;

import com.hafiz.www.enums.CampaignTypeEnum;
import com.hafiz.www.event.CampaignHandlerEvent;
import com.hafiz.www.handler.ICampaignHandler;
import com.hafiz.www.spring.SpringAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @Description: 价格折扣活动操作器
 * @author hafiz.zhang
 * @create 2017/11/28 20:52.
 */
@Component
public class PriceDiscountCampaignHandler implements ICampaignHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(PriceDiscountCampaignHandler.class);

    @PostConstruct
    public void init() {
        CampaignHandlerEvent event = new CampaignHandlerEvent(this);
        SpringAware.getApplicationContext().publishEvent(event);
    }

    @Override
    public CampaignTypeEnum getCampaignType() {
        return CampaignTypeEnum.PRICE_DISCOUNT;
    }

    @Override
    public String calculate() {
        LOGGER.info("价格折扣活动计算毛利率");
        return "价格折扣活动计算毛利率";
    }
}

3.抢购类活动实现类

package com.hafiz.www.handler.impl;

import com.hafiz.www.enums.CampaignTypeEnum;
import com.hafiz.www.event.CampaignHandlerEvent;
import com.hafiz.www.handler.ICampaignHandler;
import com.hafiz.www.spring.SpringAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @Description: 抢购活动操作器
 * @author: hafiz.zhang
 * @create: 2017/11/28 20:52.
 */
@Component
public class PanicBuyCampaignHandler implements ICampaignHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(PanicBuyCampaignHandler.class);

    @PostConstruct
    public void init() {
        CampaignHandlerEvent event = new CampaignHandlerEvent(this);
        SpringAware.getApplicationContext().publishEvent(event);
    }

    @Override
    public CampaignTypeEnum getCampaignType() {
        return CampaignTypeEnum.PANIC_BUY;
    }

    @Override
    public String calculate() {
        LOGGER.info("抢购活动计算毛利率");
        return "抢购活动计算毛利率";
    }
}

还有另外几种活动类型的实现方式,为了避免篇幅过长不一一列举。

4.新工厂实现方式

package com.hafiz.www.handler;

import com.hafiz.www.enums.CampaignTypeEnum;
import com.hafiz.www.event.CampaignHandlerEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author hafiz.zhang
 * @description: 活动操作器工厂类
 * @date Created in 2017/11/28 20:59.
 */
@Component
public class CampaignHandlerFactory implements ApplicationListener<CampaignHandlerEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(CampaignHandlerFactory.class);

    private static Map<CampaignTypeEnum, ICampaignHandler> handlerMap = new ConcurrentHashMap<>();

    /**
     * 通过活动类型获取对应的操作器
     *
     * @param discountType 活动类型
     *
     * @return
     */
    public static ICampaignHandler getHandler(Integer discountType) {
        CampaignTypeEnum discountTypeEnum = CampaignTypeEnum.getEnumById(discountType);
        ICampaignHandler handler = handlerMap.get(discountTypeEnum);
        return handler;
    }

    /**
     * 注册绑定不同类型活动对应的活动操作器
     *
     * @param handler 活动操作器
     *
     */
    private void registerHandler(ICampaignHandler handler) {
        CampaignTypeEnum discountType = handler.getCampaignType();
        LOGGER.info("开始绑定{}类型的活动处理器", discountType.getName());
        handlerMap.put(discountType, handler);
    }

    @Override
    public void onApplicationEvent(CampaignHandlerEvent event) {
        ICampaignHandler handler = (ICampaignHandler) event.getSource();
        this.registerHandler(handler);
    }
}

说明 :新的工厂类中通过实现Spring的事件监听,接收到监听以后,直接获取事件源,保存在本地Map中,就很优雅。这样新增活动类型的时候工厂类完全不需要修改,而且现有类也不需要修改,只需要进行对新的活动类型扩展就好了。符合了软件开发中的开闭环原则。看起来很棒~

5.工具类SpringAware

package com.hafiz.www.spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

/**
 * @author hafiz.zhang
 * @description: spring 上下文工具类
 * @date Created in 2017/11/28 21:07.
 */
public class SpringAware implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;

    public SpringAware() {
    }

    @Override
    public void setApplicationContext(ApplicationContext ac) throws BeansException {
        applicationContext = ac;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T> T getBean(String name) {
        return (T) applicationContext.getBean(name);
    }

    public static void rollBack() {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

 

其他Spring的配置以及测试用例等代码不再单独贴出,源码地址:https://github.com/hafizzhang/code-optimize.git

七、总结

​  在实际工作中,我们会碰到很多这种可以通过设计模式以及Java特性来实现优雅代码的机会,这个时候我们一定不能只为了省事写出烂代码,这样不但对自己的成长没有任何的好处,而且会对以后维护者造成很大困扰,我们要在保证工期和质量的前提下尽量的把代码写的优雅一点,尽量考虑到可扩展性以及可维护性等。这样才能在技术上有所提高,才能够自我成长。两全其美,何乐而不为呢?

当前文章:http://hnhdqp.com/16414.html

发布时间:2019-02-20 03:12:09

广东麻将手机版下载 可信吗 皮皮四川麻将手机版下载 50个提现的捕鱼游戏下载 齐齐乐有没有作弊器 棋牌类游戏哪个最好 最新棋牌游戏下载排行 亲友湖南棋牌有挂吗

编辑:平丁

相关新闻

识破电话诈骗,网络电话帮大忙

2019-02-20 00:51:54

定安钢装集团有限责任公司

佳县召开县委反腐败协调小组扩大会议

2019-02-20 03:43:05

辽源藤悠瞬科贸有限公司

陈绍辉闪耀文交剧院 回忆坎坷主持路

2019-02-20 04:53:37

乐山廖匙房产交易有限公司

盘点2014年网络理财 非P2P网贷莫属!

2019-02-20 03:24:06

保亭稚鹤商贸有限公司

热门推荐

  • 梁静茹回应被冒充 网友称多发自拍照亮相
  • 缅甸若开邦首府今早遭数枚炸弹袭击
  • 年货礼盒:百草味坚果1358g装79→69元/艾贝拉每日坚果25g×30袋128→73元
  • 芜湖高空坠物致人死亡案宣判:81户业主和物业共赔50万
  • 试吃的橙子甜到发腻 原来商家的刀上“有鬼”
  • 《绝地求生》新服饰曝光:风格多样,还有XB1版套装
  • 北师MBA个性化教育 多元化培养商科管理人才
  • 《火影忍者》一直在伪装的角色 临死方见英雄本色
  • 也门政府军基地遭自杀袭击 至少120名士兵死伤
  • 青岛大爷大妈快车道暴走引热议 交警替其找健身场所
  • 河北新闻网版权所有 本站点信息未经允许不得复制或镜像 法律顾问:手机版现金棋牌 网上玩棋牌游戏赚钱
  • 网络棋牌频道象棋节目 copyright ? 2000 - 2016
  • 新闻热线:0311-67563366 广告热线:0311-67562966 新闻投诉:0311-67562994
  • 冀ICP备 09047539号-1 | 互联网新闻信息服务许可证编号:1312006002
  • 广播电视节目制作经营许可证(冀)字第101号|信息网络传播视听节目许可证0311618号
  • 可以支付宝提现炸金花 众乐棋牌怎么样 最新棋牌捕鱼送金币 2019最火现金棋牌官网