《编程导论(Java)》在9.3.1回调中,介绍了好莱坞法则/好莱坞原则(Hollywood principle)p287,并将它作为回调的近义词,即当程序中使用了回调,那么你的程序应用了"好莱坞法则"。
- Hollywood principle:"Don't call me; I'll call you." (don't call us, we'll call you)
对于好莱坞原则的解释,在各种书籍、文献中极其混乱。本文介绍《编程导论(Java)》中对好莱坞原则的解释,以及为什么要这样解释。不可避免地,本文会把一些著名文献中的解释作为反面例子。
重写 别了,DIP、IoC
不懂递归,不要说学过算法;
不懂回调,不要说学过编程;
1.引子:多态
图1 依赖于抽象类型、针对接口编程、遵循OCP 代码的基本结构
Client有方法test,代码为:
IServer s = new Server();
s.foo(5);
对上述代码的解释:“s被初始化后,将按照s实际指向的对象类型(Server), 动态绑定foo()的代码块。”
这是面向对象中基本的解释方式,后面的讨论将涉及到这一解释。
这里,我设定了一个前提:我不喜欢对上述代码的其他云山雾绕的解释!
2.回调

非回调代码,如果不考虑OCP,图1中的Client可以直接依赖于Server;而在图2所示的回调的应用场景中,上层的Client直接依赖于下层的Server,而下层的Server不能够依赖Client,因而不得不在下层(或基础设施/框架中)定义一个Client的父类型,如接口IClient。
- 回调与通常的非回调代码,从类图和其自身代码上,没有区别。
- (为了使用回调)回调机制不得不在下层(或基础设施/框架中)定义一个Client的父类型IClient,它定义了回调foo(int)的方法头(方法的接口)
- 回调与通常的非回调代码,使用的技术不过是动态绑定/多态。
3.好莱坞法则
- 好莱坞原则、回调不改变分层结构的依赖方向——
控制反转Inversion Of Control/IoC这个乱七八糟术语没有存在的价值(充其量说明了软件的用户体验)。 - 本书中,好莱坞原则中的me是下层模块!
- 如果不采用通知方式——应用应用好莱坞原则,上层可以轮询。(自己编写一个演示程序)
4.类层次与好莱坞原则
Don’t call us, we’ll call you.
The parent class tells the child class the same thing.”
- 从依赖关系上看,按照分层的观点,子类是上层模块、父类是下层模块(如果不在同一层的话)。因为子类可以(必须的)依赖父类型,你不可能将父类型放在上层,而让下层(的子类)依赖于上层。所以上文中的下划线部分本身就是错误的。
- 如“1.引子:多态”所言,有动态绑定,在类层次中使用回调、好莱坞原则的解释是一种极其无聊的解释,而且令人困惑。
- 按照他的说法,好莱坞原则“应该”意味着“上层调用下层而下层不得调用上层”;而“上层调用下层而下层不得调用上层”,我们称之为单向依赖,需要搞一个多此一举的“好莱坞原则”作为单向依赖的同义词吗?当然,如果上层模块说"Don't call me; I'll call you.",非常符合该字面的解读,这种上层模块所说的好莱坞原则,和白开水一样,没有营养。
- 不管模板方法的细节,如“1.引子:多态”所言,s.foo(5)动态绑定,完全不需要”父类调用子类的操作“的说法。父类不可能知道子类的附加的操作,那么s.foo(5)是Client调用IServer的foo然后IServer调用子类Server的overridr方法foo?
- [ S w e 8 5 ]的原文:Don't call us, we'll call you (Hollywood's Law): A tool should arrange for Tajo tonotify it when the user wishes to communicate some event to the tool, rather than adopt an 'ask the user for a command and execute it' model.",和本文的【3.好莱坞法则】一致,而非【设计模式】的滥用。
- 按照面向对象的一般概念,子类是一个父类,父类动物有eat()方法,那么我们喂狗吃的时候即new Dog().eat(),有没有人说:”我喂动物吃,而动物调用狗的吃方法“,”我又喂动物吃,而动物调用猫的eat()方法“?太别扭了。
- 在分层结构中,上层依赖于下层,依赖必须是单向的。他的书中的图11.2除了看起来有点道理外,层次真的能够”倒置“吗?假设图11.2中的Utility是JDK或某个框架,你倒置给我看看。
- 他的书中的图11.2中的三个包,如果忽略policy、mechanism和Utility的寓意,从上到下事实上是Utility-mechanism-policy的普通结构,从结构上没有任何特别的地方;如果强调policy、mechanism和Utility的寓意,而且按照依赖的单向性,父类必须是下层模块,因而图11.2并无意义,实践中充其量将所谓的”policy server interface“等放入公共模块(而非好看地与Policy Layer放在一个包中)。所以DIP的“倒置”没有什么营养。从软件开发管理的角度,DIP是有启发意义的,但是DIP既不是架构设计的原则,也不是面向对象类关系的设计原则。
- 低层模块不得”实现高层模块中声明并被高层模块调用的接口“。正如反面例子之一的第一条反驳,你不可能将父类型放在上层,而让下层(的子类)依赖于上层。
5.小结:谁的好莱坞原则
如果站在上层模块的角度,me是上层模块,所说的好莱坞法则是对的,它反映了分层结构的依赖单向性。(没有再讨论的话题了)