由装饰模式巩固继承
最近学习《大话设计模式》,在学习的过程中又加深了对OO的理解,诸如abstract和virtual的区别之类的问题有了清晰的认识。今天通过装饰模式,重温OO的继承,巩固子类于父类的构造函数调用,子类调用父类方法等问题。
先看一段代码:
1 | class Person |
然后我们在主函数中实例化子类Man
1 | Man jack = new Man(); |
结果会怎样?学习过OO的新手都知道结果是
在实例化Man的时候却优先带出了父类Person,这是因为Man作为子类,将继承父类Person的方法(当然,是共有的,即public,若是爸爸的存折,小孩子当然不能拿过来玩),也就是子类实例化时,把父类能够继承的方法、属性”拷贝“到自身为己用。这是一个倒推的过程,从金字塔的底端一直找到最高端,然后从上到下”展现“出来。
简单的例子便于了解,而复杂一点的就不太容易看明白了,下面请看:
装饰模式,动态的给一个对象添加一些额外的职责,就增加功能来说,设计模式生成子类更为灵活。
源代码引用自《大话设计模式》
Person类:
1 | class Person |
Finery类:(继承Person)
1 | class Finery : Person |
杂类: (继承Finery)
1 | class LeatherShoes : Finery |
先分析一下,LeatherShoes,BigTrouser和Tshirt均继承自Finery,也就是说对这三个类实例化时,先调用的是Finery的构造函数。Finery中的Decorator方法由于是public,则同样被“拷贝”到各子类中为它们所用。而Finery又继承自Person类,当Finery构造函数调用时,又优先调用了Person的构造函数,并“拷贝”了Person的方法。
最后的结果应该是:
实例化LeatherShoes,BigTrouser和Tshirt任一个时
Person的构造函数被调用(是无参数的)
Person的show方法作为虚方法被拷贝至Finery
Finery的构造函数被调用
Finery重写了虚方法show
子类LeatherShoes,BigTrouser和Tshirt 的构造函数被调用
子类LeatherShoes,BigTrouser和Tshirt重写了虚方法show
即是一个倒推,顺寻展示的过程
在子类LeatherShoes,BigTrouser和Tshirt中的show方法中我们可以看到
1 | Console.WriteLine("***"); |
这样的语句有何作用?
同实例化一样,也是倒推的过程,只不过这次针对的不是构造函数,而是show这个方法了。
具体完整的看一遍:
1 | Person my = new Person("Sonic"); |
Person的实例化传递了参数“Sonic”,这时调用的是Person的带参数构造函数
1 | public Person(string name) |
三个子类的实例化,其倒推和展示过程已经讲过
1 | qx.Decorator(my); |
这是LeatherShoes的对象 qx 继承了父类Finery的方法Decorator,参数是Person的对象my。
来看一下Finery的Decorator是做什么的:
1 | protected Person component; |
首先定义一个Person对象component,这时 component 应为null,若此时我们没有传进来
qx.Decorator(my),而直接调用Finery的show,那么
component.show()是不执行的,也就是Person中的show不执行。现在我们将my传进来,component = my,将Person的两个对象建立起联系,此时让
Finery执行show,那么component的show 即 my的show,也就是名字为“Sonic”的Person将show出来。(有点绕)
当然,我们这里没有让它执行show,只是通过Decorator把参数传了进去。因为现在进行的是装饰的过程,没有装饰完是不需要展示出来的。
1 | kk.Decorator(qx); |