CJC(二): abstract、子类与多态的单例模式

    CJC是Common Java Cookbook的缩写, 这是一本介绍ApacheCommon开源项目的电子书 . 在这里,CJC代表我对其源码研究的系列博客.为什么要研究它?若有兴趣请看另一篇博客,避害趋利 .
------------------------  
    接着上篇 ,这里介绍"abstract与设计模式", abstract有啥好介绍的? 与设计模式? 为了解决这个问题我们从ToStringBuilder怎么实现说起.

    看ToStringBuilder的源码发现, 这个封装了三个属性:StringBuffer类型的buffer,Object类型的object和ToStringStyle类型的style. buffer是用来装最终结果的, object指的是要toString的那个对象,这两个属性都不用多说, style是个新定义的类, 它是来啥的(ToStringBuilder利用这个类来管理最终toString显示内容的格式,即是否分行显示, 是否要显示属性名,分隔符又都用哪些)? 再往下又看到ToStringBuilder类中所有的方法append都是通过调用属性style的相应方法实现的.这样通过组合方式来达到代码共用及 功能调用与实现的分隔也不是第一次见了, 有些好奇的是ToStringStyle是干啥的? 它的append方法具体是怎么实现的? 这里面是否隐藏着什么秘密?
    带着这些问题, 去看ToStringStyle源码. ToStringStyle是一个abstract的类, 有六个子类, 如下所示:    
看源码时,发现一个有意思的问题: 六个子类中有五个是private static修饰的内部类. 这样组合在自己写的代码中可是一次也没用过的.这样的处理有什么好处? 
  
顺 着问题往下追. 从abstract这个关键字说起, 既然是一个抽象类, 它又有那么多的子类,一般的理解: 抽象类可能会有一些方法也是abstract的, 不同的子类以不同的方式来实现这些个abstract方法. 验证下自己的猜测,看源码,可ToStringStyle里没有一个方法是abstract的! 六个子类中除StandardToStringStyle外的几个static内部类外,没有一个那怕是覆盖下非abstract的方法! 这就更不可思议了, 不过直观告诉我,这样的不可思议往往预示着新的收获.

新的收获应该有, 但现在却理不出头绪了, 通往新收获的被破口又在哪呢? 死扣这个类的关系是得不出答案了, 看看它们的应用. 五个private static的内部类无一例外的都是在ToStringStyle类里有了调用, 随后再放到public static final修饰的属性中, 属性名与子类名对应,如MULTI_LINE_STYLE与MultiLineToStringStyle说的是一回事. 这又怎么样呢? 还是看不出线索. 再回过头来看在toString方法中调用, 有这样的ToStringStyle.SIMPLE_STYLE使用方式. 电光火石间想起了ToStringStyle类文档描述: These classes are intended to be used as Singletons. There is no need to instantiate a new style each time. A program will generally use one of the predefined constants on this class. 对,对, 就这个predefined!现在所有类继承处理就是为了这个predefined.

    突破口找到了, 再回过头来想想. 其实这里边也没有什么值得大惊小怪的: 这种策略实际上是单例模式的一种衍生.一般常见的单例模式返回一个自己类的对象, 而这里是返回子类的对象. 有些奇特的是,ToStringStyle通过那些子类对象把一些常用的配置进行了固化处理, 这也就是predefined的由来. 而利用abstract,ToStringStyle类不让再生成新的对象.

    不过这里有一个问题: toString时的显示格式设置不可能就那么五种, 那么多set方法的组合可以设置出太多种结果, 如果某种情况下这五种predefined的方式不行怎么办? ToStringStyle又是抽象的, 我们也不能生成一个对象再自己设置. 继承一个子类出来,再new不就得了? 对, 就是这种方式. ToStringStyle也替我们想到了, StandardToStringStyle就是专门来干这个的, 咱们可以new一个StandardToStringStyle对象, 再随意地设置显示格式.

    这个收获写完了, 现在再具体总结下:
        1, 在ToStringBuilder里,通过属性ToStringBuilder来分离功能的调用与实现. 通过上面的分析,我们也能看到实现是很复杂的, 要考虑多种输出格式(及多种类型的输入内容). 若设计之初, 把功能的实现与调用都揉合到ToStringBuilder类里, 那就乱成一锅粥了, 与软件设计中的分而治之思想背通而驰.
        2, 单例模式耳熟能详了,但像今天这个通过子类来达到多态的单例还是第一次见. 再进一步看, 通过子类StandardToStringStyle提供了一个更为灵活的扩展.
        3, 真切地体会到内部类的一个新用法, 而不仅仅是Swing中那样老套的clickListener的实现.
        4, 一个重要的一点, 这样的设计考虑, 若只看书是学不到的.

你可能感兴趣的:(设计模式,swing,配置管理,项目管理)