你一定要知道业务开发最常用的两种设计模式

一、背景

很多做业务开发的同学,很多认为平时写业务代码工作就是简单的增删改查,没有挑战,写的代码不会像一些开源框架那么优雅,随着你积累的经验越来越多,你应该跳出这种思维,业务代码也可以写的很优雅,也可以有较好的可读性扩展性

我们可以观察公司内,或者团队内工作时间长一点的同事写的代码,一般都可以找到可以学习的代码。如果你读过Spring源码的同学可以知道,Spring代码有一个非常大的特点就是扩展性极强,他扩展性强一个很重要的原因是恰当的使用了很多设计模式。

本文将结合案例分析平时业务开发中使用频率最高的两种设计模式<<策略模式>>与<<责任链模式>>。

二、策略模式

以支付功能为例子,我们知道支付一般都支持多种支付方式,我们支付功能在后端发起,不同的支付方式其实就是策略,我们可以通过策略模式来完成支付功能。将不同的支付方式代码进行解耦。

public interface PaymentStrategy {
    void pay(double amount);
}

public class WeChatPaymentStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        // 微信支付逻辑
    }
}

public class AlipayPaymentStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        // 支付宝支付逻辑
    }
}
import java.util.HashMap;
import java.util.Map;

public class PaymentStrategyFactory {
    private Map<String, PaymentStrategy> strategies = new HashMap<>();

    public void registerStrategy(String name, PaymentStrategy strategy) {
        strategies.put(name, strategy);
    }

    public PaymentStrategy getStrategy(String name) {
        return strategies.get(name);
    }
}

使用策略模式:

public class Main {
    public static void main(String[] args) {
        PaymentStrategyFactory factory = new PaymentStrategyFactory();

        // 注册支付策略
        factory.registerStrategy("wechat", new WeChatPaymentStrategy());
        factory.registerStrategy("alipay", new AlipayPaymentStrategy());

        // 获取支付策略
        PaymentStrategy wechatStrategy = factory.getStrategy("wechat");
        PaymentStrategy alipayStrategy = factory.getStrategy("alipay");

        // 使用支付策略
        wechatStrategy.pay(100.0);
        alipayStrategy.pay(150.0);
    }
}

通过上方实际例子,我们可以发现策略模式很好的将不同的支付方式进行了解耦,如果业务需要新增一种支付方式,我们不需要改原先的支付方式代码,这样可以达到对扩展开发,对修复关闭的设计原则,对于测试范围也可控了。

三、异步形式的责任链模式

责任链模式在业务开发中也是可以使用频率高的设计模式,我们以展示商品为例:

[图片上传失败...(image-3cc4a9-1715505779722)]

商品页面,包含商品标题,主图等基础信息,商品价格,商品优惠活动,商品库存等等。

在微服务架构中,商品基础信息,商品价格,商品优惠活动,商品库存都是一个独立的领域服务,他们通过rpc进行通信,如果我们一个一个调用,这样代码看起来就是一本流水账,过程式编码,整体的响应时间也会拉长。最初的想法可能是这样写的:

1、查询商品基础信息
2、查询商品价格
3、查询商品活动
4、查询商品库存

由于这几个服务逻辑比较独立,其实是可以并行调用,我们可以结合责任链模式CompletableFuture进行优化。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

// 商品信息类
class ProductInfo {
    //模拟商品基础信息
    private String basicInfo;
    //商品价格
    private double price;
    //模拟商品活动信息
    private String activity;
    //模拟商品库存
    private int inventory;

    // 省略构造函数、getter和setter
}

// 定义责任链节点接口 补全商品处理接口
interface ServiceHandler {
    CompletableFuture<Void> handle(ProductInfo productInfo);
}

// 实现商品基础信息补全节点
class BasicInfoServiceHandler implements ServiceHandler {
    @Override
    public CompletableFuture<Void> handle(ProductInfo productInfo) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        // 模拟异步调用外部服务,修改商品信息对象
        CompletableFuture.runAsync(() -> {
            // 补充商品基础信息数据
            productInfo.setBasicInfo("...");
            future.complete(null);
        });
        return future;
    }
}

// 实现商品价格补全节点
class PriceServiceHandler implements ServiceHandler {
    @Override
    public CompletableFuture<Void> handle(ProductInfo productInfo) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        // 模拟异步调用外部服务,修改商品信息对象
        CompletableFuture.runAsync(() -> {
            // 补充商品价格数据
            productInfo.setPrice(100.0);
            future.complete(null);
        });
        return future;
    }
}

// 实现商品活动补全节点
class ActivityServiceHandler implements ServiceHandler {
    @Override
    public CompletableFuture<Void> handle(ProductInfo productInfo) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        // 模拟异步调用外部服务,修改商品信息对象
        CompletableFuture.runAsync(() -> {
            // 补充商品活动数据
            productInfo.setActivity("...");
            future.complete(null);
        });
        return future;
    }
}

// 实现商品库存服务节点
class InventoryServiceHandler implements ServiceHandler {
    @Override
    public CompletableFuture<Void> handle(ProductInfo productInfo) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        // 模拟异步调用外部服务,修改商品信息对象
        CompletableFuture.runAsync(() -> {
            // 补充商品库存数据
            productInfo.setInventory(100);
            future.complete(null);
        });
        return future;
    }
}

// 责任链
class ServiceHandlerChain {
    private List<ServiceHandler> handlers = new ArrayList<>();

    public void addHandler(ServiceHandler handler) {
        handlers.add(handler);
    }

    public ProductInfo execute(ProductInfo productInfo) {
        CompletableFuture<Void>[] futures = handlers.stream()
                .map(handler -> handler.handle(productInfo))
                .toArray(CompletableFuture[]::new);
        //等待所有的异步补全任务处理完成   
        CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(futures);
        allOfFuture.join(); // 等待所有异步操作完成
        return productInfo;
    }
}

调用责任链,实现商品信息补全:

public class Main {
    public static void main(String[] args) {
        // 创建商品信息对象
        ProductInfo productInfo = new ProductInfo();

        // 创建责任链
        ServiceHandlerChain chain = new ServiceHandlerChain();
        chain.addHandler(new BasicInfoServiceHandler());
        chain.addHandler(new PriceServiceHandler());
        chain.addHandler(new ActivityServiceHandler());
        chain.addHandler(new InventoryServiceHandler());

        // 执行责任链
        ProductInfo result = chain.execute(productInfo);

        // 处理最终的商品信息对象
    }
}

通过责任链模式+CompletableFuture优化调整,我们将商品各自补全逻辑进行拆分互不依赖,如果需要展示商品其他信息可以扩展新节点,而且每个节点都是异步化处理,提升整体响应速度

四、总结

本文结合实际例子对于业务开发工作中最常用两个设计模式进行了总结,适当使用设计模式可以把一些业务需求实现的更加优雅,对于未来的扩展性也打下了基础,给后期开发测试都减少了工作量,设计模式可以结合我们实际业务适当调整,变成适合我们自己业务的模式,比如上面的异步形式的责任链

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容