前言
在说设计模式这个东西之前,我在这里必须强调的是,任何设计模式的使用都要看上下文,不能单纯的为了设计模式而使用设计模式。这一点是很多学设计模式的人都没有正确理解的,很多人往往只看到某些设计模式可以去匹配某些代码,或者说某些设计模式可以用来修改某些代码,比如之前很多人就喜欢去用策略模式去把代码中的if else无脑的干掉,然后自以为写出了优雅的代码,这种被博客刷多了所留下的后遗症真的是让我无力吐槽。
这个思想很重要:设计模式的使用需要看上下文,而不仅仅是可以那段代码。
正文
废话说完了,我们开始我们本篇文章要说的委派模式,这个玩意其实不属于23种设计模式之一的,但它还是面向对象常用的设计模式之一。实际要怎么用,大家可以参考下面的例子了。
委派模式从字面上面理解的话,可以是这样的,指的是在做某件具体的事情的时候,把整个这件事情或者是这个事情的某个部分的交给了他人做,这个事情也许是我整个链路的一部分,但是复杂度比较高的时候或者是已经有别的人能够很好的处理的情况下(注意这是两种情况),我完全可以让别人做,因此委派给别人。
我们来看看我们在之前文章中提到过的spring统一资源加载这里的PathMatchingResourcePatternReslover这个类,由于它实现了ResourcePatternReslover这个接口,而ResourcePatternReslover又继承了ResourceLoader这个接口,因此它必须实现ResourceLoader中getResource这个方法,我们来看看它是怎么实现的:
@Override public Resource getResource(String location) { return getResourceLoader().getResource(location); }
我们再来看看这里面的getResourceLoader方法:
public ResourceLoader getResourceLoader() { return this.resourceLoader; }
那么这个this.resourceLoader是哪的呢,来看看PathMatchingResourcePatternReslover的构造方法:
public PathMatchingResourcePatternResolver() { this.resourceLoader = new DefaultResourceLoader(); } public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) { Assert.notNull(resourceLoader, "ResourceLoader must not be null"); this.resourceLoader = resourceLoader; }
看到这里相信大家已经看明白了吧,PathMatchingResourcePatternReslover的getResource其实就是完完全全的委派给了resourceLoader来做的。Spring其他地方使用这个的还有很多,就不一一列举了。
我们来看看标准的委派模式的代码吧:
public interface Target { void doSomeThing(); }
@Component public class BDelegate implements Target { @Override public void doSomeThing() { System.out.println("B"); } }
@Component public class ADelegate implements Target { @Override public void doSomeThing() { System.out.println("A"); } }
@Component public class Boss implements Target{ @Autowired private List<Target> targets; @Override public void doSomeThing() { targets.forEach(Target::doSomeThing); } }
一个超简单的例子了。稍微增加点解释下哈,实际使用的时候Boss未必要实现Target接口,Boss中的逻辑也可以是段包含着ADelegate或BDelegate的很复杂的逻辑,总之就是Boss自己没干活交给了ADelegate以及BDelegate两个类而已。