设计模式实战思路-持续优化项目中的坏味道

1、策略模式

1)针对项目中出现的if和多个else if处理逻辑去处理多个类似的逻辑,且多个if、else if中处理的是较为复杂的逻辑,可以使用策略模式去实现,举例:定义一个实现逻辑接口,其他实现类去实现这个逻辑接口

2) 简单逻辑,且针对两三个if else if不用进行优化

3)简单逻辑,三个以上的if else if,可以使用switsh case进行优化

2、观察者模式

1)用于订单状态变化推送第三方数据或者其他逻辑(小项目可以手写观察者接口和列表;大项目直接使用 Spring 事件或消息队列)

2)涉及到系统中包含订单状态变化需要发送待办、处理数据等、贯穿整个订单的生命周期都可以使用

注:如果只是简单的一个变更使用观察者模式就有点太重了,可以使用Future(获取返回值)或者线程池去实现优化

这里以 Spring 事件去实现观察者模式:

// 订单状态变更事件 这里的属性根据实际情况添加推送第三方或者其他操作需要的数据格式
public class ProgressStatusChangeEvent extends ApplicationEvent {
    public ProgressStatusChangeEvent(Progress progress, Enums.ProgressStatus currentStatus, ResultDto resultDto) {
       super(progress);
       this.progress = progress;
       this.currentStatus = currentStatus;
       this.resultDto = resultDto;
    }

    private final Progress progress;

    private final Enums.ProgressStatus currentStatus;

    private ResultDto resultDto;
}


// 订单服务发布事件
@Service
public class OrderService {
    @Autowired
    private ApplicationEventPublisher publisher;

    public void changeState(Progress progress, ResultDto resultDto) {
      
         publisher.publishEvent(new ProgressStatusChangeEvent(progress, Enums.ProgressStatus.CONSULATE_SUBMIT, resultDto));
    }
}

// 第三方推送监听器
@Component
public class ThirdPartyPushListener {
    @Async  // 异步执行,不阻塞主流程
    @EventListener
    public void handleOrderStateChange(OrderStateChangeEvent event) {
        // 执行具体的推送逻辑
    }
}

3、适配器模式

做「接口转换器」,把原有不兼容的接口,转换成调用方期望的统一接口,原有代码不用修改,解决接口格式不匹配问题

1)对接多个业务系统获取不同数据源的告警数据转换成统一的数据格式保存

        1)定义统一数据格式

        2)定义适配器接口

        3)实现适配器接口

        4)对接入系统数据做统一数据格式转换

/**
 * 定义统一数据格式
 */
@Setter
@Getter
public class ExternalDataIn {
    /**
     * 系统来源
     */
    private String sys;

    /**
     * 业务数据
     */
    private String data;
}



/**
 * 实现适配器接口
 */
public class ASystemConverter implements ExternalDataAdapter {

    @Override
    public ExternalDataIn dataConvert(String data) {
        ExternalDataIn externalDataIn = new ExternalDataIn();
        return externalDataIn;
    }
}


/**
 * 实现适配器接口进行统一数据格式转换
 */
public class ASystemConverter implements ExternalDataAdapter {

    @Override
    public ExternalDataIn dataConvert(String data) {
        ExternalDataIn externalDataIn = new ExternalDataIn();
        return externalDataIn;
    }
}


4、工厂模式

5、模版方法模式

1)针对业务流程的基本执行步骤是固定的,部分可选,可使用模板方式去实现

2)需要个性化实现的,定义为abstract, 由子类去实现

3)不是固定步骤的,定义为abstract, 由子类去实现

4)固定步骤的由父类模板方式实现

5)父类定义方法执行顺序

/**
 * 模板定义
 */
public abstract class DataParseTemplate {
    public final void parse() {
        getSourceData();
        dataConvert();
        checkData();
        saveData();
        sendOthers();
    }

    /**
     * 接入原始数据
     */
    abstract void getSourceData();

    /**
     * 数据转换
     */
    private void dataConvert() {
        System.out.println("统一数据转换");
    }

    /**
     * 数据校验
     */
    void checkData() {
        System.out.println("统一数据校验");
    }

    /**
     * 保存数据
     */
    abstract void saveData();

    /**
     * 推送第三方
     */
    abstract void sendOthers();

}


/**
 * 具体实现步骤
 */
@Service
public class ASystemDealService extends  DataParseTemplate {
    @Override
    void getSourceData() {
        System.out.println("A system 数据已接入");
    }

    @Override
    void saveData() {
        System.out.println("A system 数据已保存");
    }

    @Override
    void sendOthers() {
        System.out.println("A system 邮箱通知用户");
    }
}

6、责任链模式

责任链模式是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

1)审批工作流审批:请假审批、报销审批、合同审批等,每一级领导有不同的审批权限

2)拦截器:请求依次经过编码过滤器、登录校验过滤器、权限校验过滤器、日志过滤器,最终到达控制器

3)业务逻辑校验:下单时验证库存、验证用户积分、验证风控规则等,每个规则是一个处理器,依次执行,任一规则失败则中断。登录校验:账号密码、图形验证码、手机验证码

4)数据处理:原始日志 → 格式清洗 → 敏感词过滤 → 字段提取 → 入库

5)缓存策略:多级缓存(如本地缓存 → Redis → 数据库)可以构成责任链

这里以登录校验为例,验证责任链模式:


/**
 * 责任链抽象类
 */
public abstract class ReponseChain {

    public void setNextChain(ReponseChain nextChain) {
        this.nextChain = nextChain;
    }

    public abstract void doHandle(LoginInfo data);


    public void doNext(LoginInfo data){
        this.nextChain.doHandle(data);
    }

    ReponseChain nextChain;
}


/**
 * 账号密码验证实现
 */
@Slf4j
public class LoginNamePassword extends  ReponseChain {
    @Override
    public void doHandle(LoginInfo data) {
        if (data.getLoginName().equals("root") && data.getPassword().equals("root")) {
            log.info("账号密码正确");
            // 进行下一步验证
            this.doNext(data);
        } else {
            log.info("账号密码错误");
        }

    }
}


/**
 * 图形验证码验证实现
 */
@Slf4j
public class ImageVerifyCode extends  ReponseChain{
    @Override
    public void doHandle(LoginInfo data) {
        if (data.getImageVerifyCode().equals("1234")) {
            log.info("验证图形验证码成功");
            // 进行下一步验证
            this.doNext(data);
        } else {
            log.info("验证图形验证码错误");
        }
    }


}


/**
 * 手机验证码验证实现
 */
@Slf4j
public class PhoneVerifyCode extends  ReponseChain{

    @Override
    public void doHandle(LoginInfo data) {
        if (data.getPhoneVerifyCode().equals("123456")) {
            log.info("验证手机验证码通过");
            //this.nextChain.doNext(data);
        } else {
            log.info("验证手机验证码失败");
        }
    }
}


/**
 * 验证
 */

public class Test {
    public static void main(String[] args) {
        LoginNamePassword loginNamePassword = new LoginNamePassword();
        ImageVerifyCode imageVerifyCode = new ImageVerifyCode();
        PhoneVerifyCode phoneVerifyCode = new PhoneVerifyCode();

        loginNamePassword.setNextChain(imageVerifyCode);
        imageVerifyCode.setNextChain(phoneVerifyCode);

        // 验证手机验证码
        LoginInfo loginInfo2 = new LoginInfo();
        loginInfo2.setLoginName("root");
        loginInfo2.setPassword("root");
        loginInfo2.setImageVerifyCode("1234");
        loginInfo2.setPhoneVerifyCode("123456");
        loginNamePassword.doHandle(loginInfo2);
    }
}


输出:
09:03:54.099 [main] INFO com.example.demo.service.LoginNamePassword -- 账号密码正确
09:03:55.900 [main] INFO com.example.demo.service.ImageVerifyCode -- 验证图形验证码成功
09:03:55.900 [main] INFO com.example.demo.service.PhoneVerifyCode -- 验证手机验证码通过

持续更新。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值