A Look At Design

    在开始介绍各种Controller之前,我们先来讨论个重要的设计原则。在学习不同的Controller的时候,一个Spring的新手会遇到大量的标示为final的方法,这些情况常常发生在子类中覆写Controller的一些方法的时候。虽然这让我们很沮丧,但是这样做,是有重要的原因的。
    想要了解Spring开发者的意图,我们必须要知道面向对象设计(object-oriented design)中所强调开闭原则(Open-Closed Principle).这个原则定义如下:软件实体必须对扩展开放,对修改关闭(Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification). 换句话说,这个原则强调的是一个类必须保护自己被改变的同时还要良好的支持扩展(a class should protect itself from alteration while at the same time providing well-defined extension points)。
    猛地一看,感觉这两个目标好像是相互矛盾的,除了扩展之外还有其他的方式改变一个类行为吗?一个良好的面向对象设计会在封装(encapsulation)上给与很大的力度,因为它不仅可以隐藏数据还可以隐藏实现细节。开闭原则强调一个类不仅要防止外部影响(就像很多时候我们做的那样,标示很多方法为private),并且也要防止内部的干扰。内部干扰可以是任何熟知类内部结构的东西,像子类(which are in a much more powerful position to modify the behavior of a class).
    一个遵循开闭原则(Open-Closed Principle)的设计良好的类(well-designed)认为子类存在潜在的伤害(harmful),这也就是为什么你会看到很多方法都是final的。 没有了final的修饰符,子类可以覆写父类的任何非private的方法。方法的覆写存在着非常大的潜在伤害,因为它可能忽略或者改变类原来的实现意图。任何方法的重新定义都可能影响到父类与系统之间的契约(contract),导致潜在的逻辑混乱。
    但是你可以说你覆写方法的时候,可以简单的调用super.doMethod()来保证原来方法的逻辑运行(从而保证原来的方法定义),这个恰恰就是问题的症结之所在,就像没有任何的办法来保证覆写方法时一定会调用super.doMethod(). 还有,方法到底是应该在覆写代码的前面还是后面调用呢?这种不确定性对意图在不同系统中使用的lib来说,是不可接受的。
    无论如何,一个lib库如果想要被广泛的时候的话,就必须允许个性化的需求,也就是对扩展开放(open for extension).如果允许类的行为改变,你就应该允许类被扩展。扩展一般都是定义好得回调方法(callback methods)(在Spring中默认命名为为onXxx()). 这些回调(callback)方法意图就是被覆写(overridden),因为它们没有触及类的核心逻辑代码,因为所有的核心逻辑方法都被标记上final了。它会掉用一个或者更多的扩展方法来允许子类增加额外的行为。
    为了更好的说明这个原则,我们来看一下Controller接口的高层次的实现就是org.springframework.web.servlet.mvc.AbstractController. 这个类是Controller在高层次(类的继承机构)上的一个简单实现,无论如何,它提供了一个很好的开闭原则的例子,并且提供了一个学习Controoller的很好的切入点。

你可能感兴趣的:(spring,数据结构,Web,mvc,servlet)