关于设计模式的理论文章已经有很多,但开发者真正困惑的往往不是"什么是单例模式",而是"这个模式在我的小程序里到底该怎么用"。理论如果不落地,就只是一些抽象的概念。今天这篇文章,我们把之前讨论过的几种常见设计模式放到真实的小程序开发场景中,看看它们是如何解决具体问题的,希望能为你提供可直接参考的代码组织思路。
在小程序中,用户登录信息是一个典型的需要全局唯一实例的数据。用户在小程序中的登录状态、openid、昵称头像等信息,在整个应用生命周期内只需要存储一份,多个页面都需要读取和修改。
使用单例模式管理用户信息,可以创建一个用户管理模块,它内部维护一个私有的用户数据对象,对外提供获取和更新的方法。多个页面引用的是同一个模块实例,对数据的修改在所有页面中同步生效。这种方式避免了将用户信息通过页面参数层层传递的繁琐,也保证了数据的一致性。相比直接挂载到全局对象上,单例模式提供了更清晰的接口和更好的可控性。
购物车数据更新后,多个页面需要同步刷新显示最新的商品数量和总价。如果通过页面间的直接调用来实现,页面之间的耦合会非常紧密,后期维护困难。
观察者模式在这里可以发挥很好的作用。创建一个购物车事件中心,商品列表页在加入购物车时发布一个"购物车更新"事件,购物车页面和商品详情页都订阅了这个事件。当事件发生时,订阅的页面自动刷新自己的数据。新增一个需要响应购物车变化的页面,只需要订阅事件即可,不需要修改任何已有的代码。事件的发送者和接收者彼此不知道对方的存在,通过事件中心完成了解耦。
在电商小程序中,订单对象的创建涉及不同类型订单的差异化逻辑。实物订单需要计算运费和库存锁定,虚拟商品订单只需要发货逻辑,预售订单有特殊的发货时间。
使用工厂模式,可以创建一个订单工厂函数,根据订单类型返回对应的订单处理对象。调用方不需要关心不同类型订单的创建细节,只需要告诉工厂需要什么类型的订单。当新增一种订单类型时,只需要在工厂中添加对应的分支,所有调用工厂的地方自动获得新类型的支持,无需逐一修改。这种模式把对象创建的复杂性封装在工厂内部,让调用方的代码保持简洁。
优惠券的折扣计算方式多种多样,满减券、折扣券、免邮券、单品券的计算规则各不相同,而且规则会随着运营活动频繁变化。
策略模式为每种优惠券定义一个独立的计算策略,每个策略实现相同的计算接口。在计算订单优惠时,根据用户使用的优惠券类型选择对应的策略执行计算。新增一种优惠券类型时,只需要新增一个策略实现,不会影响已有策略的稳定性。规则调整时也只需要修改对应的策略文件,避免了在同一个函数中写满各种if-else分支的臃肿代码。
小程序的数据上报是一个横切关注点,几乎每个用户操作都需要记录埋点数据。如果在每个点击事件中手动调用埋点方法,会产生大量重复代码,而且埋点逻辑和业务逻辑混在一起,可读性差。
装饰器模式通过高阶函数的方式来解决这个问题。创建一个埋点装饰器,它接收一个业务函数作为参数,返回一个新的函数。这个新函数在执行原业务逻辑之前先执行埋点上报,然后调用原函数。业务函数本身不需要做任何修改,只需要在导出时被装饰器包裹即可。后续埋点规则发生变化时,只需要修改装饰器内部的逻辑,所有被装饰的函数自动生效,业务代码完全不受影响。
小程序需要接入多个第三方服务,每个服务的接口签名和数据格式都不相同。支付接口、物流查询接口、短信发送接口分别来自不同的服务商,它们的调用方式和返回结构五花八门。
适配器模式为每个第三方服务创建一个适配器,适配器将外部接口转换为小程序内部统一的调用方式。业务层只依赖适配器的统一接口,不直接依赖具体的第三方服务。当需要更换服务商时,只需要替换对应的适配器实现,业务代码完全不需要改动。这种模式在需要对接多个异构系统时非常实用,把变化隔离在适配层,保持核心业务的稳定。
在实际项目中,单一模式往往不足以应对复杂的业务需求,多种模式组合使用是常见的情况。一个复杂的订单处理流程,可能同时使用工厂模式创建订单对象、策略模式计算价格、观察者模式通知状态变更、装饰器模式完成数据上报。
模式组合的关键是理解每种模式解决的核心问题,然后在合适的层次上应用合适的模式。模式之间不应该互相干扰,各自负责自己领域的问题,通过清晰的接口协作。过度使用设计模式会让代码变得晦涩难懂,保持简洁始终是更重要的原则。模式是工具箱中的工具,知道用什么工具解决什么问题很重要,但更重要的是知道什么时候不需要用工具。