
看 Spring 源码里的设计模式很多时候你得绕好几层才能看到模式的全貌。Dubbo 不一样它用模式用得很明目张胆——连类名都告诉你了。Protocol、ProxyFactory、Cluster、LoadBalance……这些接口和实现之间的关系就是设计模式教科书级别的案例。今天拆 4 个最典型的。1. SPI 工厂方法扩展点加载机制Dubbo 最核心的设计不是某个设计模式而是它自己的 SPI 扩展机制。但这个机制的底层就是工厂方法模式。java // ExtensionLoader 本质是一个工厂 public class ExtensionLoaderT { // 根据名字创建扩展实例 — 典型工厂方法 public T getExtension(String name) { HolderObject holder getOrCreateHolder(name); Object instance holder.get(); if (instance null) { synchronized (holder) { instance holder.get(); if (instance null) { instance createExtension(name); // 创建具体实例 holder.set(instance); } } } return (T) instance; } }调用方式java Protocol protocol ExtensionLoader .getExtensionLoader(Protocol.class) .getExtension(dubbo); // 按名字加载具体实现ExtensionLoader是工厂Protocol是产品接口DubboProtocol、HttpProtocol、RedisProtocol是具体产品。你不需要new任何实现类只要在META-INF/dubbo下配置好扩展点工厂帮你创建。这比 Spring 的BeanFactory更直白你不需要注解、不需要容器启动一行代码拿到扩展实例。2. 装饰器模式Protocol 的包装链Dubbo 里的Protocol接口有一堆实现有些是真正的协议有些是装饰器。看源码java // 真正的协议实现 public class DubboProtocol implements Protocol { ... } public class HttpProtocol implements Protocol { ... }// 装饰器给 Protocol 加功能 public class ProtocolFilterWrapper implements Protocol { private Protocol protocol; // 持有被装饰对象public T ExporterT export(InvokerT invoker) { // 先构建 Filter 链再委托给真正的 Protocol return protocol.export(buildInvokerChain(invoker, ...)); }}public class ProtocolListenerWrapper implements Protocol { private Protocol protocol;public T ExporterT export(InvokerT invoker) { // 加监听器逻辑再委托 return protocol.export(invoker); }}public class QosProtocolWrapper implements Protocol { private Protocol protocol; // 加 QoS 功能 } 加载顺序先加载真正的 Protocol然后用装饰器一层层包上去QosProtocolWrapper └─ ProtocolListenerWrapper └─ ProtocolFilterWrapper └─ DubboProtocol ← 真正干活的这就是装饰器模式的精髓不修改原始类通过包装给它加功能。而且装饰器可以无限叠加每层只管自己的事。Dubbo 的 Filter 链也是装饰器模式的变体。你在配置文件里加的timeout、monitor、exceptionFilter都是一个个装饰器把Invoker包装后返回。3. 策略模式负载均衡这是 Dubbo 里最容易看懂的策略模式——连接口名都叫LoadBalancejava SPI(RandomLoadBalance.NAME) public interface LoadBalance { T InvokerT select(ListInvokerT invokers, URL url, Invocation invocation); }四种策略实现java public class RandomLoadBalance extends AbstractLoadBalance { ... } // 随机 public class RoundRobinLoadBalance extends AbstractLoadBalance { ... } // 轮询 public class LeastActiveLoadBalance extends AbstractLoadBalance { ... } // 最少活跃 public class ConsistentHashLoadBalance extends AbstractLoadBalance { ... } // 一致性哈希选择哪个策略配置决定xml dubbo:reference loadbalanceroundrobin /运行时通过 SPI 加载对应实现java LoadBalance lb ExtensionLoader .getExtensionLoader(LoadBalance.class) .getExtension(roundrobin);不写 if-else不写 switch策略的切换完全由配置驱动。新增负载均衡算法写个实现类 配置文件就行零侵入。4. 模板方法模式AbstractProtocolDubbo 的Protocol接口有两个核心方法export暴露服务和refer引用服务。不同协议的实现逻辑差异很大但有些公共步骤是固定的。AbstractProtocol把这些公共步骤抽到模板方法里java public abstract class AbstractProtocol implements Protocol {// 模板方法暴露服务的公共骨架 public T ExporterT export(InvokerT invoker) throws RpcException { // 公共逻辑校验 URL、记录 exporter 等 URL url invoker.getUrl(); String key serviceKey(url); ExporterT exporter doExport(invoker, url, key); // 子类实现 exporterMap.put(key, exporter); return exporter; } // 子类必须实现的抽象方法 protected abstract T ExporterT doExport(InvokerT invoker, URL url, String key); // 引用服务同理 public T InvokerT refer(ClassT type, URL url) throws RpcException { // 公共逻辑 InvokerT invoker doRefer(type, url); // 子类实现 return invoker; } protected abstract T InvokerT doRefer(ClassT type, URL url);} DubboProtocol只需要关心自己的doExport和doReferjava public class DubboProtocol extends AbstractProtocol { Override protected T ExporterT doExport(InvokerT invoker, URL url, String key) { // 打开 Server、注册到注册中心 等 Dubbo 特有逻辑 openServer(url); optimizeSerialization(url); return new DubboExporter(invoker, key, exporterMap); } }公共逻辑不重复协议特有逻辑各写各的。如果以后新增一个 gRPC 协议继承AbstractProtocol实现两个方法就行。跟 Spring 对比着看| 模式 | Spring 怎么用 | Dubbo 怎么用 | |------|-------------|------------| | 工厂方法 | BeanFactory 各种 FactoryBean | ExtensionLoader 直接按名加载 | | 装饰器 | BeanWrapper、各种 Proxy | ProtocolFilterWrapper 等包装链 | | 策略 | Resource 接口不同实现 | LoadBalance 接口不同实现 | | 模板方法 | AbstractApplicationContext | AbstractProtocol |Dubbo 的特点是用得更裸没有 IoC 容器帮你管理生命周期模式就是模式代码里一目了然。看 Spring 源码你得先搞懂容器机制才能看到模式看 Dubbo 源码模式直接摊开在你面前。对初学者来说Dubbo 源码是比 Spring 更好的设计模式学习材料——不是因为它更高级而是因为它更直白。我在做的小程序「爪爪代码冒险记」也在尝试用更直白的方式讲设计模式漫画答题的形式比啃源码轻松一点感兴趣可以搜搜。